From 2e994684de6d326ff3dc4674986a10fbf28e3511 Mon Sep 17 00:00:00 2001 From: HenryNguyen5 <6404866+HenryNguyen5@users.noreply.github.com> Date: Sat, 27 Apr 2024 13:04:49 -0400 Subject: [PATCH 01/45] Remove codecov (#13020) --- codecov.yml | 15 - tools/bin/codecov | 1888 --------------------------------------- tools/bin/go_core_tests | 2 - 3 files changed, 1905 deletions(-) delete mode 100644 codecov.yml delete mode 100755 tools/bin/codecov diff --git a/codecov.yml b/codecov.yml deleted file mode 100644 index a70f1961e36..00000000000 --- a/codecov.yml +++ /dev/null @@ -1,15 +0,0 @@ -comment: false - -coverage: - status: - project: - default: - threshold: 1% - -github_checks: - annotations: false - -ignore: - - 'contracts/' # Disabled due to solidity-coverage not reporting coverage - - 'core/internal' - - 'core/scripts' diff --git a/tools/bin/codecov b/tools/bin/codecov deleted file mode 100755 index 36513ce06df..00000000000 --- a/tools/bin/codecov +++ /dev/null @@ -1,1888 +0,0 @@ -#!/usr/bin/env bash - -# Apache License Version 2.0, January 2004 -# https://github.com/codecov/codecov-bash/blob/master/LICENSE - -set -e +o pipefail - -VERSION="1.0.6" - -codecov_flags=( ) -url="https://codecov.io" -env="$CODECOV_ENV" -service="" -token="" -search_in="" -# shellcheck disable=SC2153 -flags="$CODECOV_FLAGS" -exit_with=0 -curlargs="" -curlawsargs="" -dump="0" -clean="0" -curl_s="-s" -name="$CODECOV_NAME" -include_cov="" -exclude_cov="" -ddp="$HOME/Library/Developer/Xcode/DerivedData" -xp="" -files="" -save_to="" -direct_file_upload="" -cacert="$CODECOV_CA_BUNDLE" -gcov_ignore="-not -path './bower_components/**' -not -path './node_modules/**' -not -path './vendor/**'" -gcov_include="" - -ft_gcov="1" -ft_coveragepy="1" -ft_fix="1" -ft_search="1" -ft_s3="1" -ft_network="1" -ft_xcodellvm="1" -ft_xcodeplist="0" -ft_gcovout="1" -ft_html="0" -ft_yaml="0" - -_git_root=$(git rev-parse --show-toplevel 2>/dev/null || hg root 2>/dev/null || echo "$PWD") -git_root="$_git_root" -remote_addr="" -if [ "$git_root" = "$PWD" ]; -then - git_root="." -fi - -branch_o="" -build_o="" -commit_o="" -pr_o="" -prefix_o="" -network_filter_o="" -search_in_o="" -slug_o="" -tag_o="" -url_o="" -git_ls_files_recurse_submodules_o="" -package="bash" - -commit="$VCS_COMMIT_ID" -branch="$VCS_BRANCH_NAME" -pr="$VCS_PULL_REQUEST" -slug="$VCS_SLUG" -tag="$VCS_TAG" -build_url="$CI_BUILD_URL" -build="$CI_BUILD_ID" -job="$CI_JOB_ID" - -beta_xcode_partials="" - -proj_root="$git_root" -gcov_exe="gcov" -gcov_arg="" - -b="\033[0;36m" -g="\033[0;32m" -r="\033[0;31m" -e="\033[0;90m" -y="\033[0;33m" -x="\033[0m" - -show_help() { -cat << EOF - - Codecov Bash $VERSION - - Global report uploading tool for Codecov - Documentation at https://docs.codecov.io/docs - Contribute at https://github.com/codecov/codecov-bash - - - -h Display this help and exit - -f FILE Target file(s) to upload - - -f "path/to/file" only upload this file - skips searching unless provided patterns below - - -f '!*.bar' ignore all files at pattern *.bar - -f '*.foo' include all files at pattern *.foo - Must use single quotes. - This is non-exclusive, use -s "*.foo" to match specific paths. - - -s DIR Directory to search for coverage reports. - Already searches project root and artifact folders. - -t TOKEN Set the private repository token - (option) set environment variable CODECOV_TOKEN=:uuid - - -t @/path/to/token_file - -t uuid - - -n NAME Custom defined name of the upload. Visible in Codecov UI - - -e ENV Specify environment variables to be included with this build - Also accepting environment variables: CODECOV_ENV=VAR,VAR2 - - -e VAR,VAR2 - - -k prefix Prefix filepaths to help resolve path fixing - - -i prefix Only include files in the network with a certain prefix. Useful for upload-specific path fixing - - -X feature Toggle functionalities - - -X gcov Disable gcov - -X coveragepy Disable python coverage - -X fix Disable report fixing - -X search Disable searching for reports - -X xcode Disable xcode processing - -X network Disable uploading the file network - -X gcovout Disable gcov output - -X html Enable coverage for HTML files - -X recursesubs Enable recurse submodules in git projects when searching for source files - -X yaml Enable coverage for YAML files - - -N The commit SHA of the parent for which you are uploading coverage. If not present, - the parent will be determined using the API of your repository provider. - When using the repository provider's API, the parent is determined via finding - the closest ancestor to the commit. - - -R root dir Used when not in git/hg project to identify project root directory - -F flag Flag the upload to group coverage metrics - - -F unittests This upload is only unittests - -F integration This upload is only integration tests - -F ui,chrome This upload is Chrome - UI tests - - -c Move discovered coverage reports to the trash - -z FILE Upload specified file directly to Codecov and bypass all report generation. - This is inteded to be used only with a pre-formatted Codecov report and is not - expected to work under any other circumstances. - -Z Exit with 1 if not successful. Default will Exit with 0 - - -- xcode -- - -D Custom Derived Data Path for Coverage.profdata and gcov processing - Default '~/Library/Developer/Xcode/DerivedData' - -J Specify packages to build coverage. Uploader will only build these packages. - This can significantly reduces time to build coverage reports. - - -J 'MyAppName' Will match "MyAppName" and "MyAppNameTests" - -J '^ExampleApp$' Will match only "ExampleApp" not "ExampleAppTests" - - -- gcov -- - -g GLOB Paths to ignore during gcov gathering - -G GLOB Paths to include during gcov gathering - -p dir Project root directory - Also used when preparing gcov - -x gcovexe gcov executable to run. Defaults to 'gcov' - -a gcovargs extra arguments to pass to gcov - - -- Override CI Environment Variables -- - These variables are automatically detected by popular CI providers - - -B branch Specify the branch name - -C sha Specify the commit sha - -P pr Specify the pull request number - -b build Specify the build number - -T tag Specify the git tag - - -- Enterprise -- - -u URL Set the target url for Enterprise customers - Not required when retrieving the bash uploader from your CCE - (option) Set environment variable CODECOV_URL=https://my-hosted-codecov.com - -r SLUG owner/repo slug used instead of the private repo token in Enterprise - (option) set environment variable CODECOV_SLUG=:owner/:repo - (option) set in your codecov.yml "codecov.slug" - -S PATH File path to your cacert.pem file used to verify ssl with Codecov Enterprise (optional) - (option) Set environment variable: CODECOV_CA_BUNDLE="/path/to/ca.pem" - -U curlargs Extra curl arguments to communicate with Codecov. e.g., -U "--proxy http://http-proxy" - -A curlargs Extra curl arguments to communicate with AWS. - - -- Debugging -- - -d Don't upload, but dump upload file to stdout - -q PATH Write upload file to path - -K Remove color from the output - -v Verbose mode - -EOF -} - - -say() { - echo -e "$1" -} - - -urlencode() { - echo "$1" | curl -Gso /dev/null -w "%{url_effective}" --data-urlencode @- "" | cut -c 3- | sed -e 's/%0A//' -} - -swiftcov() { - _dir=$(dirname "$1" | sed 's/\(Build\).*/\1/g') - for _type in app framework xctest - do - find "$_dir" -name "*.$_type" | while read -r f - do - _proj=${f##*/} - _proj=${_proj%."$_type"} - if [ "$2" = "" ] || [ "$(echo "$_proj" | grep -i "$2")" != "" ]; - then - say " $g+$x Building reports for $_proj $_type" - dest=$([ -f "$f/$_proj" ] && echo "$f/$_proj" || echo "$f/Contents/MacOS/$_proj") - # shellcheck disable=SC2001 - _proj_name=$(echo "$_proj" | sed -e 's/[[:space:]]//g') - # shellcheck disable=SC2086 - xcrun llvm-cov show $beta_xcode_partials -instr-profile "$1" "$dest" > "$_proj_name.$_type.coverage.txt" \ - || say " ${r}x>${x} llvm-cov failed to produce results for $dest" - fi - done - done -} - - -# Credits to: https://gist.github.com/pkuczynski/8665367 -parse_yaml() { - local prefix=$2 - local s='[[:space:]]*' w='[a-zA-Z0-9_]*' - local fs - fs=$(echo @|tr @ '\034') - sed -ne "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \ - -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" "$1" | - awk -F"$fs" '{ - indent = length($1)/2; - vname[indent] = $2; - for (i in vname) {if (i > indent) {delete vname[i]}} - if (length($3) > 0) { - vn=""; if (indent > 0) {vn=(vn)(vname[0])("_")} - printf("%s%s%s=\"%s\"\n", "'"$prefix"'",vn, $2, $3); - } - }' -} - -if [ $# != 0 ]; -then - while getopts "a:A:b:B:cC:dD:e:f:F:g:G:hi:J:k:Kn:p:P:Q:q:r:R:s:S:t:T:u:U:vx:X:Zz:N:-" o - do - codecov_flags+=( "$o" ) - case "$o" in - "-") - echo -e "${r}Long options are not supported${x}" - exit 2 - ;; - "?") - ;; - "N") - parent=$OPTARG - ;; - "a") - gcov_arg=$OPTARG - ;; - "A") - curlawsargs="$OPTARG" - ;; - "b") - build_o="$OPTARG" - ;; - "B") - branch_o="$OPTARG" - ;; - "c") - clean="1" - ;; - "C") - commit_o="$OPTARG" - ;; - "d") - dump="1" - ;; - "D") - ddp="$OPTARG" - ;; - "e") - env="$env,$OPTARG" - ;; - "f") - if [ "${OPTARG::1}" = "!" ]; - then - exclude_cov="$exclude_cov -not -path '${OPTARG:1}'" - - elif [[ "$OPTARG" = *"*"* ]]; - then - include_cov="$include_cov -or -path '$OPTARG'" - - else - ft_search=0 - if [ "$files" = "" ]; - then - files="$OPTARG" - else - files="$files -$OPTARG" - fi - fi - ;; - "F") - if [ "$flags" = "" ]; - then - flags="$OPTARG" - else - flags="$flags,$OPTARG" - fi - ;; - "g") - gcov_ignore="$gcov_ignore -not -path '$OPTARG'" - ;; - "G") - gcov_include="$gcov_include -path '$OPTARG'" - ;; - "h") - show_help - exit 0; - ;; - "i") - network_filter_o="$OPTARG" - ;; - "J") - ft_xcodellvm="1" - ft_xcodeplist="0" - if [ "$xp" = "" ]; - then - xp="$OPTARG" - else - xp="$xp\|$OPTARG" - fi - ;; - "k") - prefix_o=$(echo "$OPTARG" | sed -e 's:^/*::' -e 's:/*$::') - ;; - "K") - b="" - g="" - r="" - e="" - x="" - ;; - "n") - name="$OPTARG" - ;; - "p") - proj_root="$OPTARG" - ;; - "P") - pr_o="$OPTARG" - ;; - "Q") - # this is only meant for Codecov packages to overwrite - package="$OPTARG" - ;; - "q") - save_to="$OPTARG" - ;; - "r") - slug_o="$OPTARG" - ;; - "R") - git_root="$OPTARG" - ;; - "s") - if [ "$search_in_o" = "" ]; - then - search_in_o="$OPTARG" - else - search_in_o="$search_in_o $OPTARG" - fi - ;; - "S") - # shellcheck disable=SC2089 - cacert="--cacert \"$OPTARG\"" - ;; - "t") - if [ "${OPTARG::1}" = "@" ]; - then - token=$(< "${OPTARG:1}" tr -d ' \n') - else - token="$OPTARG" - fi - ;; - "T") - tag_o="$OPTARG" - ;; - "u") - url_o=$(echo "$OPTARG" | sed -e 's/\/$//') - ;; - "U") - curlargs="$OPTARG" - ;; - "v") - set -x - curl_s="" - ;; - "x") - gcov_exe=$OPTARG - ;; - "X") - if [ "$OPTARG" = "gcov" ]; - then - ft_gcov="0" - elif [ "$OPTARG" = "coveragepy" ] || [ "$OPTARG" = "py" ]; - then - ft_coveragepy="0" - elif [ "$OPTARG" = "gcovout" ]; - then - ft_gcovout="0" - elif [ "$OPTARG" = "xcodellvm" ]; - then - ft_xcodellvm="1" - ft_xcodeplist="0" - elif [ "$OPTARG" = "fix" ] || [ "$OPTARG" = "fixes" ]; - then - ft_fix="0" - elif [ "$OPTARG" = "xcode" ]; - then - ft_xcodellvm="0" - ft_xcodeplist="0" - elif [ "$OPTARG" = "search" ]; - then - ft_search="0" - elif [ "$OPTARG" = "xcodepartials" ]; - then - beta_xcode_partials="-use-color" - elif [ "$OPTARG" = "network" ]; - then - ft_network="0" - elif [ "$OPTARG" = "s3" ]; - then - ft_s3="0" - elif [ "$OPTARG" = "html" ]; - then - ft_html="1" - elif [ "$OPTARG" = "recursesubs" ]; - then - git_ls_files_recurse_submodules_o="--recurse-submodules" - elif [ "$OPTARG" = "yaml" ]; - then - ft_yaml="1" - fi - ;; - "Z") - exit_with=1 - ;; - "z") - direct_file_upload="$OPTARG" - ft_gcov="0" - ft_coveragepy="0" - ft_fix="0" - ft_search="0" - ft_network="0" - ft_xcodellvm="0" - ft_gcovout="0" - include_cov="" - ;; - *) - echo -e "${r}Unexpected flag not supported${x}" - ;; - esac - done -fi - -say " - _____ _ - / ____| | | -| | ___ __| | ___ ___ _____ __ -| | / _ \\ / _\` |/ _ \\/ __/ _ \\ \\ / / -| |___| (_) | (_| | __/ (_| (_) \\ V / - \\_____\\___/ \\__,_|\\___|\\___\\___/ \\_/ - Bash-$VERSION - -" - -# check for installed tools -# git/hg -if [ "$direct_file_upload" = "" ]; -then - if [ -x "$(command -v git)" ]; - then - say "$b==>$x $(git --version) found" - else - say "$y==>$x git not installed, testing for mercurial" - if [ -x "$(command -v hg)" ]; - then - say "$b==>$x $(hg --version) found" - else - say "$r==>$x git nor mercurial are installed. Uploader may fail or have unintended consequences" - fi - fi -fi -# curl -if [ -x "$(command -v curl)" ]; -then - say "$b==>$x $(curl --version)" -else - say "$r==>$x curl not installed. Exiting." - exit ${exit_with}; -fi - -search_in="$proj_root" - -#shellcheck disable=SC2154 -if [ "$JENKINS_URL" != "" ]; -then - say "$e==>$x Jenkins CI detected." - # https://wiki.jenkins-ci.org/display/JENKINS/Building+a+software+project - # https://wiki.jenkins-ci.org/display/JENKINS/GitHub+pull+request+builder+plugin#GitHubpullrequestbuilderplugin-EnvironmentVariables - service="jenkins" - - # shellcheck disable=SC2154 - if [ "$ghprbSourceBranch" != "" ]; - then - branch="$ghprbSourceBranch" - elif [ "$GIT_BRANCH" != "" ]; - then - branch="$GIT_BRANCH" - elif [ "$BRANCH_NAME" != "" ]; - then - branch="$BRANCH_NAME" - fi - - # shellcheck disable=SC2154 - if [ "$ghprbActualCommit" != "" ]; - then - commit="$ghprbActualCommit" - elif [ "$GIT_COMMIT" != "" ]; - then - commit="$GIT_COMMIT" - fi - - # shellcheck disable=SC2154 - if [ "$ghprbPullId" != "" ]; - then - pr="$ghprbPullId" - elif [ "$CHANGE_ID" != "" ]; - then - pr="$CHANGE_ID" - fi - - build="$BUILD_NUMBER" - # shellcheck disable=SC2153 - build_url=$(urlencode "$BUILD_URL") - -elif [ "$CI" = "true" ] && [ "$TRAVIS" = "true" ] && [ "$SHIPPABLE" != "true" ]; -then - say "$e==>$x Travis CI detected." - # https://docs.travis-ci.com/user/environment-variables/ - service="travis" - commit="${TRAVIS_PULL_REQUEST_SHA:-$TRAVIS_COMMIT}" - build="$TRAVIS_JOB_NUMBER" - pr="$TRAVIS_PULL_REQUEST" - job="$TRAVIS_JOB_ID" - slug="$TRAVIS_REPO_SLUG" - env="$env,TRAVIS_OS_NAME" - tag="$TRAVIS_TAG" - if [ "$TRAVIS_BRANCH" != "$TRAVIS_TAG" ]; - then - branch="${TRAVIS_PULL_REQUEST_BRANCH:-$TRAVIS_BRANCH}" - fi - - language=$(compgen -A variable | grep "^TRAVIS_.*_VERSION$" | head -1) - if [ "$language" != "" ]; - then - env="$env,${!language}" - fi - -elif [ "$CODEBUILD_CI" = "true" ]; -then - say "$e==>$x AWS Codebuild detected." - # https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-env-vars.html - service="codebuild" - commit="$CODEBUILD_RESOLVED_SOURCE_VERSION" - build="$CODEBUILD_BUILD_ID" - branch="$(echo "$CODEBUILD_WEBHOOK_HEAD_REF" | sed 's/^refs\/heads\///')" - if [ "${CODEBUILD_SOURCE_VERSION/pr}" = "$CODEBUILD_SOURCE_VERSION" ] ; then - pr="false" - else - pr="$(echo "$CODEBUILD_SOURCE_VERSION" | sed 's/^pr\///')" - fi - job="$CODEBUILD_BUILD_ID" - slug="$(echo "$CODEBUILD_SOURCE_REPO_URL" | sed 's/^.*:\/\/[^\/]*\///' | sed 's/\.git$//')" - -elif [ "$CI" = "true" ] && [ "$CI_NAME" = "codeship" ]; -then - say "$e==>$x Codeship CI detected." - # https://www.codeship.io/documentation/continuous-integration/set-environment-variables/ - service="codeship" - branch="$CI_BRANCH" - build="$CI_BUILD_NUMBER" - build_url=$(urlencode "$CI_BUILD_URL") - commit="$CI_COMMIT_ID" - -elif [ -n "$CF_BUILD_URL" ] && [ -n "$CF_BUILD_ID" ]; -then - say "$e==>$x Codefresh CI detected." - # https://docs.codefresh.io/v1.0/docs/variables - service="codefresh" - branch="$CF_BRANCH" - build="$CF_BUILD_ID" - build_url=$(urlencode "$CF_BUILD_URL") - commit="$CF_REVISION" - -elif [ "$TEAMCITY_VERSION" != "" ]; -then - say "$e==>$x TeamCity CI detected." - # https://confluence.jetbrains.com/display/TCD8/Predefined+Build+Parameters - # https://confluence.jetbrains.com/plugins/servlet/mobile#content/view/74847298 - if [ "$TEAMCITY_BUILD_BRANCH" = '' ]; - then - echo " Teamcity does not automatically make build parameters available as environment variables." - echo " Add the following environment parameters to the build configuration" - echo " env.TEAMCITY_BUILD_BRANCH = %teamcity.build.branch%" - echo " env.TEAMCITY_BUILD_ID = %teamcity.build.id%" - echo " env.TEAMCITY_BUILD_URL = %teamcity.serverUrl%/viewLog.html?buildId=%teamcity.build.id%" - echo " env.TEAMCITY_BUILD_COMMIT = %system.build.vcs.number%" - echo " env.TEAMCITY_BUILD_REPOSITORY = %vcsroot..url%" - fi - service="teamcity" - branch="$TEAMCITY_BUILD_BRANCH" - build="$TEAMCITY_BUILD_ID" - build_url=$(urlencode "$TEAMCITY_BUILD_URL") - if [ "$TEAMCITY_BUILD_COMMIT" != "" ]; - then - commit="$TEAMCITY_BUILD_COMMIT" - else - commit="$BUILD_VCS_NUMBER" - fi - remote_addr="$TEAMCITY_BUILD_REPOSITORY" - -elif [ "$CI" = "true" ] && [ "$CIRCLECI" = "true" ]; -then - say "$e==>$x Circle CI detected." - # https://circleci.com/docs/environment-variables - service="circleci" - branch="$CIRCLE_BRANCH" - build="$CIRCLE_BUILD_NUM" - job="$CIRCLE_NODE_INDEX" - if [ "$CIRCLE_PROJECT_REPONAME" != "" ]; - then - slug="$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME" - else - # git@github.com:owner/repo.git - slug="${CIRCLE_REPOSITORY_URL##*:}" - # owner/repo.git - slug="${slug%%.git}" - fi - pr="${CIRCLE_PULL_REQUEST##*/}" - commit="$CIRCLE_SHA1" - search_in="$search_in $CIRCLE_ARTIFACTS $CIRCLE_TEST_REPORTS" - -elif [ "$BUDDYBUILD_BRANCH" != "" ]; -then - say "$e==>$x buddybuild detected" - # http://docs.buddybuild.com/v6/docs/custom-prebuild-and-postbuild-steps - service="buddybuild" - branch="$BUDDYBUILD_BRANCH" - build="$BUDDYBUILD_BUILD_NUMBER" - build_url="https://dashboard.buddybuild.com/public/apps/$BUDDYBUILD_APP_ID/build/$BUDDYBUILD_BUILD_ID" - # BUDDYBUILD_TRIGGERED_BY - if [ "$ddp" = "$HOME/Library/Developer/Xcode/DerivedData" ]; - then - ddp="/private/tmp/sandbox/${BUDDYBUILD_APP_ID}/bbtest" - fi - -elif [ "${bamboo_planRepository_revision}" != "" ]; -then - say "$e==>$x Bamboo detected" - # https://confluence.atlassian.com/bamboo/bamboo-variables-289277087.html#Bamboovariables-Build-specificvariables - service="bamboo" - commit="${bamboo_planRepository_revision}" - # shellcheck disable=SC2154 - branch="${bamboo_planRepository_branch}" - # shellcheck disable=SC2154 - build="${bamboo_buildNumber}" - # shellcheck disable=SC2154 - build_url="${bamboo_buildResultsUrl}" - # shellcheck disable=SC2154 - remote_addr="${bamboo_planRepository_repositoryUrl}" - -elif [ "$CI" = "true" ] && [ "$BITRISE_IO" = "true" ]; -then - # http://devcenter.bitrise.io/faq/available-environment-variables/ - say "$e==>$x Bitrise CI detected." - service="bitrise" - branch="$BITRISE_GIT_BRANCH" - build="$BITRISE_BUILD_NUMBER" - build_url=$(urlencode "$BITRISE_BUILD_URL") - pr="$BITRISE_PULL_REQUEST" - if [ "$GIT_CLONE_COMMIT_HASH" != "" ]; - then - commit="$GIT_CLONE_COMMIT_HASH" - fi - -elif [ "$CI" = "true" ] && [ "$SEMAPHORE" = "true" ]; -then - say "$e==>$x Semaphore CI detected." -# https://docs.semaphoreci.com/ci-cd-environment/environment-variables/#semaphore-related - service="semaphore" - branch="$SEMAPHORE_GIT_BRANCH" - build="$SEMAPHORE_WORKFLOW_NUMBER" - job="$SEMAPHORE_JOB_ID" - pr="$PULL_REQUEST_NUMBER" - slug="$SEMAPHORE_REPO_SLUG" - commit="$REVISION" - env="$env,SEMAPHORE_TRIGGER_SOURCE" - -elif [ "$CI" = "true" ] && [ "$BUILDKITE" = "true" ]; -then - say "$e==>$x Buildkite CI detected." - # https://buildkite.com/docs/guides/environment-variables - service="buildkite" - branch="$BUILDKITE_BRANCH" - build="$BUILDKITE_BUILD_NUMBER" - job="$BUILDKITE_JOB_ID" - build_url=$(urlencode "$BUILDKITE_BUILD_URL") - slug="$BUILDKITE_PROJECT_SLUG" - commit="$BUILDKITE_COMMIT" - if [[ "$BUILDKITE_PULL_REQUEST" != "false" ]]; then - pr="$BUILDKITE_PULL_REQUEST" - fi - tag="$BUILDKITE_TAG" - -elif [ "$CI" = "drone" ] || [ "$DRONE" = "true" ]; -then - say "$e==>$x Drone CI detected." - # http://docs.drone.io/env.html - # drone commits are not full shas - service="drone.io" - branch="$DRONE_BRANCH" - build="$DRONE_BUILD_NUMBER" - build_url=$(urlencode "${DRONE_BUILD_LINK}") - pr="$DRONE_PULL_REQUEST" - job="$DRONE_JOB_NUMBER" - tag="$DRONE_TAG" - -elif [ "$CI" = "true" ] && [ "$HEROKU_TEST_RUN_BRANCH" != "" ]; -then - say "$e==>$x Heroku CI detected." - # https://devcenter.heroku.com/articles/heroku-ci#environment-variables - service="heroku" - branch="$HEROKU_TEST_RUN_BRANCH" - build="$HEROKU_TEST_RUN_ID" - commit="$HEROKU_TEST_RUN_COMMIT_VERSION" - -elif [[ "$CI" = "true" || "$CI" = "True" ]] && [[ "$APPVEYOR" = "true" || "$APPVEYOR" = "True" ]]; -then - say "$e==>$x Appveyor CI detected." - # http://www.appveyor.com/docs/environment-variables - service="appveyor" - branch="$APPVEYOR_REPO_BRANCH" - build=$(urlencode "$APPVEYOR_JOB_ID") - pr="$APPVEYOR_PULL_REQUEST_NUMBER" - job="$APPVEYOR_ACCOUNT_NAME%2F$APPVEYOR_PROJECT_SLUG%2F$APPVEYOR_BUILD_VERSION" - slug="$APPVEYOR_REPO_NAME" - commit="$APPVEYOR_REPO_COMMIT" - build_url=$(urlencode "${APPVEYOR_URL}/project/${APPVEYOR_REPO_NAME}/builds/$APPVEYOR_BUILD_ID/job/${APPVEYOR_JOB_ID}") - -elif [ "$CI" = "true" ] && [ "$WERCKER_GIT_BRANCH" != "" ]; -then - say "$e==>$x Wercker CI detected." - # http://devcenter.wercker.com/articles/steps/variables.html - service="wercker" - branch="$WERCKER_GIT_BRANCH" - build="$WERCKER_MAIN_PIPELINE_STARTED" - slug="$WERCKER_GIT_OWNER/$WERCKER_GIT_REPOSITORY" - commit="$WERCKER_GIT_COMMIT" - -elif [ "$CI" = "true" ] && [ "$MAGNUM" = "true" ]; -then - say "$e==>$x Magnum CI detected." - # https://magnum-ci.com/docs/environment - service="magnum" - branch="$CI_BRANCH" - build="$CI_BUILD_NUMBER" - commit="$CI_COMMIT" - -elif [ "$SHIPPABLE" = "true" ]; -then - say "$e==>$x Shippable CI detected." - # http://docs.shippable.com/ci_configure/ - service="shippable" - # shellcheck disable=SC2153 - branch=$([ "$HEAD_BRANCH" != "" ] && echo "$HEAD_BRANCH" || echo "$BRANCH") - build="$BUILD_NUMBER" - build_url=$(urlencode "$BUILD_URL") - pr="$PULL_REQUEST" - slug="$REPO_FULL_NAME" - # shellcheck disable=SC2153 - commit="$COMMIT" - -elif [ "$TDDIUM" = "true" ]; -then - say "Solano CI detected." - # http://docs.solanolabs.com/Setup/tddium-set-environment-variables/ - service="solano" - commit="$TDDIUM_CURRENT_COMMIT" - branch="$TDDIUM_CURRENT_BRANCH" - build="$TDDIUM_TID" - pr="$TDDIUM_PR_ID" - -elif [ "$GREENHOUSE" = "true" ]; -then - say "$e==>$x Greenhouse CI detected." - # http://docs.greenhouseci.com/docs/environment-variables-files - service="greenhouse" - branch="$GREENHOUSE_BRANCH" - build="$GREENHOUSE_BUILD_NUMBER" - build_url=$(urlencode "$GREENHOUSE_BUILD_URL") - pr="$GREENHOUSE_PULL_REQUEST" - commit="$GREENHOUSE_COMMIT" - search_in="$search_in $GREENHOUSE_EXPORT_DIR" - -elif [ "$GITLAB_CI" != "" ]; -then - say "$e==>$x GitLab CI detected." - # http://doc.gitlab.com/ce/ci/variables/README.html - service="gitlab" - branch="${CI_BUILD_REF_NAME:-$CI_COMMIT_REF_NAME}" - build="${CI_BUILD_ID:-$CI_JOB_ID}" - remote_addr="${CI_BUILD_REPO:-$CI_REPOSITORY_URL}" - commit="${CI_BUILD_REF:-$CI_COMMIT_SHA}" - slug="${CI_PROJECT_PATH}" - -elif [ "$GITHUB_ACTIONS" != "" ]; -then - say "$e==>$x GitHub Actions detected." - say " Env vars used:" - say " -> GITHUB_ACTIONS: ${GITHUB_ACTIONS}" - say " -> GITHUB_HEAD_REF: ${GITHUB_HEAD_REF}" - say " -> GITHUB_REF: ${GITHUB_REF}" - say " -> GITHUB_REPOSITORY: ${GITHUB_REPOSITORY}" - say " -> GITHUB_RUN_ID: ${GITHUB_RUN_ID}" - say " -> GITHUB_SHA: ${GITHUB_SHA}" - say " -> GITHUB_WORKFLOW: ${GITHUB_WORKFLOW}" - - # https://github.com/features/actions - service="github-actions" - - # https://help.github.com/en/articles/virtual-environments-for-github-actions#environment-variables - branch="${GITHUB_REF#refs/heads/}" - if [ "$GITHUB_HEAD_REF" != "" ]; - then - # PR refs are in the format: refs/pull/7/merge - if [[ "$GITHUB_REF" =~ ^refs\/pull\/[0-9]+\/merge$ ]]; - then - pr="${GITHUB_REF#refs/pull/}" - pr="${pr%/merge}" - fi - branch="${GITHUB_HEAD_REF}" - fi - commit="${GITHUB_SHA}" - slug="${GITHUB_REPOSITORY}" - build="${GITHUB_RUN_ID}" - build_url=$(urlencode "${GITHUB_SERVER_URL:-https://github.com}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}") - job="$(urlencode "${GITHUB_WORKFLOW}")" - - # actions/checkout runs in detached HEAD - mc= - if [ -n "$pr" ] && [ "$pr" != false ] && [ "$commit_o" == "" ]; - then - mc=$(git show --no-patch --format="%P" 2>/dev/null || echo "") - - if [[ "$mc" =~ ^[a-z0-9]{40}[[:space:]][a-z0-9]{40}$ ]]; - then - mc=$(echo "$mc" | cut -d' ' -f2) - say " Fixing merge commit SHA $commit -> $mc" - commit=$mc - elif [[ "$mc" = "" ]]; - then - say "$r-> Issue detecting commit SHA. Please run actions/checkout with fetch-depth > 1 or set to 0$x" - fi - fi - -elif [ "$SYSTEM_TEAMFOUNDATIONSERVERURI" != "" ]; -then - say "$e==>$x Azure Pipelines detected." - # https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=vsts - # https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&viewFallbackFrom=vsts&tabs=yaml - service="azure_pipelines" - commit="$BUILD_SOURCEVERSION" - build="$BUILD_BUILDNUMBER" - if [ -z "$SYSTEM_PULLREQUEST_PULLREQUESTNUMBER" ]; - then - pr="$SYSTEM_PULLREQUEST_PULLREQUESTID" - else - pr="$SYSTEM_PULLREQUEST_PULLREQUESTNUMBER" - fi - project="${SYSTEM_TEAMPROJECT}" - server_uri="${SYSTEM_TEAMFOUNDATIONSERVERURI}" - job="${BUILD_BUILDID}" - branch="${BUILD_SOURCEBRANCH#"refs/heads/"}" - build_url=$(urlencode "${SYSTEM_TEAMFOUNDATIONSERVERURI}${SYSTEM_TEAMPROJECT}/_build/results?buildId=${BUILD_BUILDID}") - - # azure/pipelines runs in detached HEAD - mc= - if [ -n "$pr" ] && [ "$pr" != false ]; - then - mc=$(git show --no-patch --format="%P" 2>/dev/null || echo "") - - if [[ "$mc" =~ ^[a-z0-9]{40}[[:space:]][a-z0-9]{40}$ ]]; - then - mc=$(echo "$mc" | cut -d' ' -f2) - say " Fixing merge commit SHA $commit -> $mc" - commit=$mc - fi - fi - -elif [ "$CI" = "true" ] && [ "$BITBUCKET_BUILD_NUMBER" != "" ]; -then - say "$e==>$x Bitbucket detected." - # https://confluence.atlassian.com/bitbucket/variables-in-pipelines-794502608.html - service="bitbucket" - branch="$BITBUCKET_BRANCH" - build="$BITBUCKET_BUILD_NUMBER" - slug="$BITBUCKET_REPO_OWNER/$BITBUCKET_REPO_SLUG" - job="$BITBUCKET_BUILD_NUMBER" - pr="$BITBUCKET_PR_ID" - commit="$BITBUCKET_COMMIT" - # See https://jira.atlassian.com/browse/BCLOUD-19393 - if [ "${#commit}" = 12 ]; - then - commit=$(git rev-parse "$BITBUCKET_COMMIT") - fi - -elif [ "$CI" = "true" ] && [ "$BUDDY" = "true" ]; -then - say "$e==>$x Buddy CI detected." - # https://buddy.works/docs/pipelines/environment-variables - service="buddy" - branch="$BUDDY_EXECUTION_BRANCH" - build="$BUDDY_EXECUTION_ID" - build_url=$(urlencode "$BUDDY_EXECUTION_URL") - commit="$BUDDY_EXECUTION_REVISION" - pr="$BUDDY_EXECUTION_PULL_REQUEST_NO" - tag="$BUDDY_EXECUTION_TAG" - slug="$BUDDY_REPO_SLUG" - -elif [ "$CIRRUS_CI" != "" ]; -then - say "$e==>$x Cirrus CI detected." - # https://cirrus-ci.org/guide/writing-tasks/#environment-variables - service="cirrus-ci" - slug="$CIRRUS_REPO_FULL_NAME" - branch="$CIRRUS_BRANCH" - pr="$CIRRUS_PR" - commit="$CIRRUS_CHANGE_IN_REPO" - build="$CIRRUS_BUILD_ID" - build_url=$(urlencode "https://cirrus-ci.com/task/$CIRRUS_TASK_ID") - job="$CIRRUS_TASK_NAME" - -elif [ "$DOCKER_REPO" != "" ]; -then - say "$e==>$x Docker detected." - # https://docs.docker.com/docker-cloud/builds/advanced/ - service="docker" - branch="$SOURCE_BRANCH" - commit="$SOURCE_COMMIT" - slug="$DOCKER_REPO" - tag="$CACHE_TAG" - env="$env,IMAGE_NAME" - -else - say "${r}x>${x} No CI provider detected." - say " Testing inside Docker? ${b}http://docs.codecov.io/docs/testing-with-docker${x}" - say " Testing with Tox? ${b}https://docs.codecov.io/docs/python#section-testing-with-tox${x}" - -fi - -say " ${e}current dir: ${x} $PWD" -say " ${e}project root:${x} $git_root" - -# find branch, commit, repo from git command -if [ "$GIT_BRANCH" != "" ]; -then - branch="$GIT_BRANCH" - -elif [ "$branch" = "" ]; -then - branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || hg branch 2>/dev/null || echo "") - if [ "$branch" = "HEAD" ]; - then - branch="" - fi -fi - -if [ "$commit_o" = "" ]; -then - if [ "$GIT_COMMIT" != "" ]; - then - commit="$GIT_COMMIT" - elif [ "$commit" = "" ]; - then - commit=$(git log -1 --format="%H" 2>/dev/null || hg id -i --debug 2>/dev/null | tr -d '+' || echo "") - fi -else - commit="$commit_o" -fi - -if [ "$CODECOV_TOKEN" != "" ] && [ "$token" = "" ]; -then - say "${e}-->${x} token set from env" - token="$CODECOV_TOKEN" -fi - -if [ "$CODECOV_URL" != "" ] && [ "$url_o" = "" ]; -then - say "${e}-->${x} url set from env" - url_o=$(echo "$CODECOV_URL" | sed -e 's/\/$//') -fi - -if [ "$CODECOV_SLUG" != "" ]; -then - say "${e}-->${x} slug set from env" - slug_o="$CODECOV_SLUG" - -elif [ "$slug" = "" ]; -then - if [ "$remote_addr" = "" ]; - then - remote_addr=$(git config --get remote.origin.url || hg paths default || echo '') - fi - if [ "$remote_addr" != "" ]; - then - if echo "$remote_addr" | grep -q "//"; then - # https - slug=$(echo "$remote_addr" | cut -d / -f 4,5 | sed -e 's/\.git$//') - else - # ssh - slug=$(echo "$remote_addr" | cut -d : -f 2 | sed -e 's/\.git$//') - fi - fi - if [ "$slug" = "/" ]; - then - slug="" - fi -fi - -yaml=$(cd "$git_root" && \ - git ls-files "*codecov.yml" "*codecov.yaml" 2>/dev/null \ - || hg locate "*codecov.yml" "*codecov.yaml" 2>/dev/null \ - || cd "$proj_root" && find . -maxdepth 1 -type f -name '*codecov.y*ml' 2>/dev/null \ - || echo '') -yaml=$(echo "$yaml" | head -1) - -if [ "$yaml" != "" ]; -then - say " ${e}Yaml found at:${x} $yaml" - if [[ "$yaml" != /* ]]; then - # relative path for yaml file given, assume relative to the repo root - yaml="$git_root/$yaml" - fi - config=$(parse_yaml "$yaml" || echo '') - - # TODO validate the yaml here - - if [ "$(echo "$config" | grep 'codecov_token="')" != "" ] && [ "$token" = "" ]; - then - say "${e}-->${x} token set from yaml" - token="$(echo "$config" | grep 'codecov_token="' | sed -e 's/codecov_token="//' | sed -e 's/"\.*//')" - fi - - if [ "$(echo "$config" | grep 'codecov_url="')" != "" ] && [ "$url_o" = "" ]; - then - say "${e}-->${x} url set from yaml" - url_o="$(echo "$config" | grep 'codecov_url="' | sed -e 's/codecov_url="//' | sed -e 's/"\.*//')" - fi - - if [ "$(echo "$config" | grep 'codecov_slug="')" != "" ] && [ "$slug_o" = "" ]; - then - say "${e}-->${x} slug set from yaml" - slug_o="$(echo "$config" | grep 'codecov_slug="' | sed -e 's/codecov_slug="//' | sed -e 's/"\.*//')" - fi -else - say " ${g}Yaml not found, that's ok! Learn more at${x} ${b}http://docs.codecov.io/docs/codecov-yaml${x}" -fi - -if [ "$branch_o" != "" ]; -then - branch=$(urlencode "$branch_o") -else - branch=$(urlencode "$branch") -fi - -if [ "$slug_o" = "" ]; -then - urlencoded_slug=$(urlencode "$slug") -else - urlencoded_slug=$(urlencode "$slug_o") -fi - -query="branch=$branch\ - &commit=$commit\ - &build=$([ "$build_o" = "" ] && echo "$build" || echo "$build_o")\ - &build_url=$build_url\ - &name=$(urlencode "$name")\ - &tag=$([ "$tag_o" = "" ] && echo "$tag" || echo "$tag_o")\ - &slug=$urlencoded_slug\ - &service=$service\ - &flags=$flags\ - &pr=$([ "$pr_o" = "" ] && echo "${pr##\#}" || echo "${pr_o##\#}")\ - &job=$job\ - &cmd_args=$(IFS=,; echo "${codecov_flags[*]}")" - -if [ -n "$project" ] && [ -n "$server_uri" ]; -then - query=$(echo "$query&project=$project&server_uri=$server_uri" | tr -d ' ') -fi - -if [ "$parent" != "" ]; -then - query=$(echo "parent=$parent&$query" | tr -d ' ') -fi - -if [ "$ft_search" = "1" ]; -then - # detect bower comoponents location - bower_components="bower_components" - bower_rc=$(cd "$git_root" && cat .bowerrc 2>/dev/null || echo "") - if [ "$bower_rc" != "" ]; - then - bower_components=$(echo "$bower_rc" | tr -d '\n' | grep '"directory"' | cut -d'"' -f4 | sed -e 's/\/$//') - if [ "$bower_components" = "" ]; - then - bower_components="bower_components" - fi - fi - - # Swift Coverage - if [ "$ft_xcodellvm" = "1" ] && [ -d "$ddp" ]; - then - say "${e}==>${x} Processing Xcode reports via llvm-cov" - say " DerivedData folder: $ddp" - profdata_files=$(find "$ddp" -name '*.profdata' 2>/dev/null || echo '') - if [ "$profdata_files" != "" ]; - then - # xcode via profdata - if [ "$xp" = "" ]; - then - # xp=$(xcodebuild -showBuildSettings 2>/dev/null | grep -i "^\s*PRODUCT_NAME" | sed -e 's/.*= \(.*\)/\1/') - # say " ${e}->${x} Speed up Xcode processing by adding ${e}-J '$xp'${x}" - say " ${g}hint${x} Speed up Swift processing by using use ${g}-J 'AppName'${x} (regexp accepted)" - say " ${g}hint${x} This will remove Pods/ from your report. Also ${b}https://docs.codecov.io/docs/ignoring-paths${x}" - fi - while read -r profdata; - do - if [ "$profdata" != "" ]; - then - swiftcov "$profdata" "$xp" - fi - done <<< "$profdata_files" - else - say " ${e}->${x} No Swift coverage found" - fi - - # Obj-C Gcov Coverage - if [ "$ft_gcov" = "1" ]; - then - say " ${e}->${x} Running $gcov_exe for Obj-C" - if [ "$ft_gcovout" = "0" ]; - then - # suppress gcov output - bash -c "find $ddp -type f -name '*.gcda' $gcov_include $gcov_ignore -exec $gcov_exe -p $gcov_arg {} +" >/dev/null 2>&1 || true - else - bash -c "find $ddp -type f -name '*.gcda' $gcov_include $gcov_ignore -exec $gcov_exe -p $gcov_arg {} +" || true - fi - fi - fi - - if [ "$ft_xcodeplist" = "1" ] && [ -d "$ddp" ]; - then - say "${e}==>${x} Processing Xcode plists" - plists_files=$(find "$ddp" -name '*.xccoverage' 2>/dev/null || echo '') - if [ "$plists_files" != "" ]; - then - while read -r plist; - do - if [ "$plist" != "" ]; - then - say " ${g}Found${x} plist file at $plist" - plutil -convert xml1 -o "$(basename "$plist").plist" -- "$plist" - fi - done <<< "$plists_files" - fi - fi - - # Gcov Coverage - if [ "$ft_gcov" = "1" ]; - then - say "${e}==>${x} Running $gcov_exe in $proj_root ${e}(disable via -X gcov)${x}" - if [ "$ft_gcovout" = "0" ]; - then - # suppress gcov output - bash -c "find $proj_root -type f -name '*.gcno' $gcov_include $gcov_ignore -exec $gcov_exe -pb $gcov_arg {} +" >/dev/null 2>&1 || true - else - bash -c "find $proj_root -type f -name '*.gcno' $gcov_include $gcov_ignore -exec $gcov_exe -pb $gcov_arg {} +" || true - fi - else - say "${e}==>${x} gcov disabled" - fi - - # Python Coverage - if [ "$ft_coveragepy" = "1" ]; - then - if [ ! -f coverage.xml ]; - then - if command -v coverage >/dev/null 2>&1; - then - say "${e}==>${x} Python coveragepy exists ${e}disable via -X coveragepy${x}" - - dotcoverage=$(find "$git_root" -name '.coverage' -or -name '.coverage.*' | head -1 || echo '') - if [ "$dotcoverage" != "" ]; - then - cd "$(dirname "$dotcoverage")" - if [ ! -f .coverage ]; - then - say " ${e}->${x} Running coverage combine" - coverage combine -a - fi - say " ${e}->${x} Running coverage xml" - if [ "$(coverage xml -i)" != "No data to report." ]; - then - files="$files -$PWD/coverage.xml" - else - say " ${r}No data to report.${x}" - fi - cd "$proj_root" - else - say " ${r}No .coverage file found.${x}" - fi - else - say "${e}==>${x} Python coveragepy not found" - fi - fi - else - say "${e}==>${x} Python coveragepy disabled" - fi - - if [ "$search_in_o" != "" ]; - then - # location override - search_in="$search_in_o" - fi - - say "$e==>$x Searching for coverage reports in:" - for _path in $search_in - do - say " ${g}+${x} $_path" - done - - patterns="find $search_in \( \ - -name vendor \ - -or -name '$bower_components' \ - -or -name '.egg-info*' \ - -or -name 'conftest_*.c.gcov' \ - -or -name .env \ - -or -name .envs \ - -or -name .git \ - -or -name .hg \ - -or -name .tox \ - -or -name .venv \ - -or -name .venvs \ - -or -name .virtualenv \ - -or -name .virtualenvs \ - -or -name .yarn-cache \ - -or -name __pycache__ \ - -or -name env \ - -or -name envs \ - -or -name htmlcov \ - -or -name js/generated/coverage \ - -or -name node_modules \ - -or -name venv \ - -or -name venvs \ - -or -name virtualenv \ - -or -name virtualenvs \ - \) -prune -or \ - -type f \( -name '*coverage*.*' \ - -or -name '*.clover' \ - -or -name '*.codecov.*' \ - -or -name '*.gcov' \ - -or -name '*.lcov' \ - -or -name '*.lst' \ - -or -name 'clover.xml' \ - -or -name 'cobertura.xml' \ - -or -name 'codecov.*' \ - -or -name 'cover.out' \ - -or -name 'codecov-result.json' \ - -or -name 'coverage-final.json' \ - -or -name 'excoveralls.json' \ - -or -name 'gcov.info' \ - -or -name 'jacoco*.xml' \ - -or -name '*Jacoco*.xml' \ - -or -name 'lcov.dat' \ - -or -name 'lcov.info' \ - -or -name 'luacov.report.out' \ - -or -name 'naxsi.info' \ - -or -name 'nosetests.xml' \ - -or -name 'report.xml' \ - $include_cov \) \ - $exclude_cov \ - -not -name '*.am' \ - -not -name '*.bash' \ - -not -name '*.bat' \ - -not -name '*.bw' \ - -not -name '*.cfg' \ - -not -name '*.class' \ - -not -name '*.cmake' \ - -not -name '*.cmake' \ - -not -name '*.conf' \ - -not -name '*.coverage' \ - -not -name '*.cp' \ - -not -name '*.cpp' \ - -not -name '*.crt' \ - -not -name '*.css' \ - -not -name '*.csv' \ - -not -name '*.csv' \ - -not -name '*.data' \ - -not -name '*.db' \ - -not -name '*.dox' \ - -not -name '*.ec' \ - -not -name '*.ec' \ - -not -name '*.egg' \ - -not -name '*.el' \ - -not -name '*.env' \ - -not -name '*.erb' \ - -not -name '*.exe' \ - -not -name '*.ftl' \ - -not -name '*.gif' \ - -not -name '*.gradle' \ - -not -name '*.gz' \ - -not -name '*.h' \ - -not -name '*.html' \ - -not -name '*.in' \ - -not -name '*.jade' \ - -not -name '*.jar*' \ - -not -name '*.jpeg' \ - -not -name '*.jpg' \ - -not -name '*.js' \ - -not -name '*.less' \ - -not -name '*.log' \ - -not -name '*.m4' \ - -not -name '*.mak*' \ - -not -name '*.md' \ - -not -name '*.o' \ - -not -name '*.p12' \ - -not -name '*.pem' \ - -not -name '*.png' \ - -not -name '*.pom*' \ - -not -name '*.profdata' \ - -not -name '*.proto' \ - -not -name '*.ps1' \ - -not -name '*.pth' \ - -not -name '*.py' \ - -not -name '*.pyc' \ - -not -name '*.pyo' \ - -not -name '*.rb' \ - -not -name '*.rsp' \ - -not -name '*.rst' \ - -not -name '*.ru' \ - -not -name '*.sbt' \ - -not -name '*.scss' \ - -not -name '*.scss' \ - -not -name '*.serialized' \ - -not -name '*.sh' \ - -not -name '*.snapshot' \ - -not -name '*.sql' \ - -not -name '*.svg' \ - -not -name '*.tar.tz' \ - -not -name '*.template' \ - -not -name '*.whl' \ - -not -name '*.xcconfig' \ - -not -name '*.xcoverage.*' \ - -not -name '*/classycle/report.xml' \ - -not -name '*codecov.yml' \ - -not -name '*~' \ - -not -name '.*coveragerc' \ - -not -name '.coverage*' \ - -not -name 'coverage-summary.json' \ - -not -name 'createdFiles.lst' \ - -not -name 'fullLocaleNames.lst' \ - -not -name 'include.lst' \ - -not -name 'inputFiles.lst' \ - -not -name 'phpunit-code-coverage.xml' \ - -not -name 'phpunit-coverage.xml' \ - -not -name 'remapInstanbul.coverage*.json' \ - -not -name 'scoverage.measurements.*' \ - -not -name 'test_*_coverage.txt' \ - -not -name 'testrunner-coverage*' \ - -print 2>/dev/null" - files=$(eval "$patterns" || echo '') - -elif [ "$include_cov" != "" ]; -then - files=$(eval "find $search_in -type f \( ${include_cov:5} \)$exclude_cov 2>/dev/null" || echo '') -elif [ "$direct_file_upload" != "" ]; -then - files=$direct_file_upload -fi - -num_of_files=$(echo "$files" | wc -l | tr -d ' ') -if [ "$num_of_files" != '' ] && [ "$files" != '' ]; -then - say " ${e}->${x} Found $num_of_files reports" -fi - -# no files found -if [ "$files" = "" ]; -then - say "${r}-->${x} No coverage report found." - say " Please visit ${b}http://docs.codecov.io/docs/supported-languages${x}" - exit ${exit_with}; -fi - -if [ "$ft_network" == "1" ]; -then - say "${e}==>${x} Detecting git/mercurial file structure" - network=$(cd "$git_root" && git ls-files $git_ls_files_recurse_submodules_o 2>/dev/null || hg locate 2>/dev/null || echo "") - if [ "$network" = "" ]; - then - network=$(find "$git_root" \( \ - -name virtualenv \ - -name .virtualenv \ - -name virtualenvs \ - -name .virtualenvs \ - -name '*.png' \ - -name '*.gif' \ - -name '*.jpg' \ - -name '*.jpeg' \ - -name '*.md' \ - -name .env \ - -name .envs \ - -name env \ - -name envs \ - -name .venv \ - -name .venvs \ - -name venv \ - -name venvs \ - -name .git \ - -name .egg-info \ - -name shunit2-2.1.6 \ - -name vendor \ - -name __pycache__ \ - -name node_modules \ - -path "*/$bower_components/*" \ - -path '*/target/delombok/*' \ - -path '*/build/lib/*' \ - -path '*/js/generated/coverage/*' \ - \) -prune -or \ - -type f -print 2>/dev/null || echo '') - fi - - if [ "$network_filter_o" != "" ]; - then - network=$(echo "$network" | grep -e "$network_filter_o/*") - fi - if [ "$prefix_o" != "" ]; - then - network=$(echo "$network" | awk "{print \"$prefix_o/\"\$0}") - fi -fi - -upload_file=$(mktemp /tmp/codecov.XXXXXX) -adjustments_file=$(mktemp /tmp/codecov.adjustments.XXXXXX) - -cleanup() { - rm -f "$upload_file" "$adjustments_file" "$upload_file.gz" -} - -trap cleanup INT ABRT TERM - - -if [ "$env" != "" ]; -then - inc_env="" - say "${e}==>${x} Appending build variables" - for varname in $(echo "$env" | tr ',' ' ') - do - if [ "$varname" != "" ]; - then - say " ${g}+${x} $varname" - inc_env="${inc_env}${varname}=$(eval echo "\$${varname}") -" - fi - done - echo "$inc_env<<<<<< ENV" >> "$upload_file" -fi - -# Append git file list -# write discovered yaml location -if [ "$direct_file_upload" = "" ]; -then - echo "$yaml" >> "$upload_file" -fi - -if [ "$ft_network" == "1" ]; -then - i="woff|eot|otf" # fonts - i="$i|gif|png|jpg|jpeg|psd" # images - i="$i|ptt|pptx|numbers|pages|md|txt|xlsx|docx|doc|pdf|csv" # docs - i="$i|.gitignore" # supporting docs - - if [ "$ft_html" != "1" ]; - then - i="$i|html" - fi - - if [ "$ft_yaml" != "1" ]; - then - i="$i|yml|yaml" - fi - - echo "$network" | grep -vwE "($i)$" >> "$upload_file" -fi -echo "<<<<<< network" >> "$upload_file" - -if [ "$direct_file_upload" = "" ]; -then - fr=0 - say "${e}==>${x} Reading reports" - while IFS='' read -r file; - do - # read the coverage file - if [ "$(echo "$file" | tr -d ' ')" != '' ]; - then - if [ -f "$file" ]; - then - report_len=$(wc -c < "$file") - if [ "$report_len" -ne 0 ]; - then - say " ${g}+${x} $file ${e}bytes=$(echo "$report_len" | tr -d ' ')${x}" - # append to to upload - _filename=$(basename "$file") - if [ "${_filename##*.}" = 'gcov' ]; - then - { - echo "# path=$(echo "$file.reduced" | sed "s|^$git_root/||")"; - # get file name - head -1 "$file"; - } >> "$upload_file" - # 1. remove source code - # 2. remove ending bracket lines - # 3. remove whitespace - # 4. remove contextual lines - # 5. remove function names - awk -F': *' '{print $1":"$2":"}' "$file" \ - | sed '\/: *} *$/d' \ - | sed 's/^ *//' \ - | sed '/^-/d' \ - | sed 's/^function.*/func/' >> "$upload_file" - else - { - echo "# path=${file//^$git_root/||}"; - cat "$file"; - } >> "$upload_file" - fi - echo "<<<<<< EOF" >> "$upload_file" - fr=1 - if [ "$clean" = "1" ]; - then - rm "$file" - fi - else - say " ${r}-${x} Skipping empty file $file" - fi - else - say " ${r}-${x} file not found at $file" - fi - fi - done <<< "$(echo -e "$files")" - - if [ "$fr" = "0" ]; - then - say "${r}-->${x} No coverage data found." - say " Please visit ${b}http://docs.codecov.io/docs/supported-languages${x}" - say " search for your projects language to learn how to collect reports." - exit ${exit_with}; - fi -else - cp "$direct_file_upload" "$upload_file" - if [ "$clean" = "1" ]; - then - rm "$direct_file_upload" - fi -fi - -if [ "$ft_fix" = "1" ]; -then - say "${e}==>${x} Appending adjustments" - say " ${b}https://docs.codecov.io/docs/fixing-reports${x}" - - empty_line='^[[:space:]]*$' - # // - syntax_comment='^[[:space:]]*//.*' - # /* or */ - syntax_comment_block='^[[:space:]]*(\/\*|\*\/)[[:space:]]*$' - # { or } - syntax_bracket='^[[:space:]]*[\{\}][[:space:]]*(//.*)?$' - # [ or ] - syntax_list='^[[:space:]]*[][][[:space:]]*(//.*)?$' - # func ... { - syntax_go_func='^[[:space:]]*func[[:space:]]*[\{][[:space:]]*$' - - # shellcheck disable=SC2089 - skip_dirs="-not -path '*/$bower_components/*' \ - -not -path '*/node_modules/*'" - - cut_and_join() { - awk 'BEGIN { FS=":" } - $3 ~ /\/\*/ || $3 ~ /\*\// { print $0 ; next } - $1!=key { if (key!="") print out ; key=$1 ; out=$1":"$2 ; next } - { out=out","$2 } - END { print out }' 2>/dev/null - } - - if echo "$network" | grep -m1 '.kt$' 1>/dev/null; - then - # skip brackets and comments - cd "$git_root" && \ - find . -type f \ - -name '*.kt' \ - -exec \ - grep -nIHE -e "$syntax_bracket" \ - -e "$syntax_comment_block" {} \; \ - | cut_and_join \ - >> "$adjustments_file" \ - || echo '' - - # last line in file - cd "$git_root" && \ - find . -type f \ - -name '*.kt' -exec \ - wc -l {} \; \ - | while read -r l; do echo "EOF: $l"; done \ - 2>/dev/null \ - >> "$adjustments_file" \ - || echo '' - fi - - if echo "$network" | grep -m1 '.go$' 1>/dev/null; - then - # skip empty lines, comments, and brackets - cd "$git_root" && \ - find . -type f \ - -not -path '*/vendor/*' \ - -not -path '*/caches/*' \ - -name '*.go' \ - -exec \ - grep -nIHE \ - -e "$empty_line" \ - -e "$syntax_comment" \ - -e "$syntax_comment_block" \ - -e "$syntax_bracket" \ - -e "$syntax_go_func" \ - {} \; \ - | cut_and_join \ - >> "$adjustments_file" \ - || echo '' - fi - - if echo "$network" | grep -m1 '.dart$' 1>/dev/null; - then - # skip brackets - cd "$git_root" && \ - find . -type f \ - -name '*.dart' \ - -exec \ - grep -nIHE \ - -e "$syntax_bracket" \ - {} \; \ - | cut_and_join \ - >> "$adjustments_file" \ - || echo '' - fi - - if echo "$network" | grep -m1 '.php$' 1>/dev/null; - then - # skip empty lines, comments, and brackets - cd "$git_root" && \ - find . -type f \ - -not -path "*/vendor/*" \ - -name '*.php' \ - -exec \ - grep -nIHE \ - -e "$syntax_list" \ - -e "$syntax_bracket" \ - -e '^[[:space:]]*\);[[:space:]]*(//.*)?$' \ - {} \; \ - | cut_and_join \ - >> "$adjustments_file" \ - || echo '' - fi - - if echo "$network" | grep -m1 '\(.c\.cpp\|.cxx\|.h\|.hpp\|.m\|.swift\|.vala\)$' 1>/dev/null; - then - # skip brackets - # shellcheck disable=SC2086,SC2090 - cd "$git_root" && \ - find . -type f \ - $skip_dirs \ - \( \ - -name '*.c' \ - -or -name '*.cpp' \ - -or -name '*.cxx' \ - -or -name '*.h' \ - -or -name '*.hpp' \ - -or -name '*.m' \ - -or -name '*.swift' \ - -or -name '*.vala' \ - \) -exec \ - grep -nIHE \ - -e "$empty_line" \ - -e "$syntax_bracket" \ - -e '// LCOV_EXCL' \ - {} \; \ - | cut_and_join \ - >> "$adjustments_file" \ - || echo '' - - # skip brackets - # shellcheck disable=SC2086,SC2090 - cd "$git_root" && \ - find . -type f \ - $skip_dirs \ - \( \ - -name '*.c' \ - -or -name '*.cpp' \ - -or -name '*.cxx' \ - -or -name '*.h' \ - -or -name '*.hpp' \ - -or -name '*.m' \ - -or -name '*.swift' \ - -or -name '*.vala' \ - \) -exec \ - grep -nIH '// LCOV_EXCL' \ - {} \; \ - >> "$adjustments_file" \ - || echo '' - - fi - - found=$(< "$adjustments_file" tr -d ' ') - - if [ "$found" != "" ]; - then - say " ${g}+${x} Found adjustments" - { - echo "# path=fixes"; - cat "$adjustments_file"; - echo "<<<<<< EOF"; - } >> "$upload_file" - rm -rf "$adjustments_file" - else - say " ${e}->${x} No adjustments found" - fi -fi - -if [ "$url_o" != "" ]; -then - url="$url_o" -fi - -if [ "$dump" != "0" ]; -then - # trim whitespace from query - say " ${e}->${x} Dumping upload file (no upload)" - echo "$url/upload/v4?$(echo "package=$package-$VERSION&$query" | tr -d ' ')" - cat "$upload_file" -else - if [ "$save_to" != "" ]; - then - say "${e}==>${x} Copying upload file to ${save_to}" - mkdir -p "$(dirname "$save_to")" - cp "$upload_file" "$save_to" - fi - - say "${e}==>${x} Gzipping contents" - gzip -nf9 "$upload_file" - say " $(du -h "$upload_file.gz")" - - query=$(echo "${query}" | tr -d ' ') - say "${e}==>${x} Uploading reports" - say " ${e}url:${x} $url" - say " ${e}query:${x} $query" - - # Full query (to display on terminal output) - query=$(echo "package=$package-$VERSION&token=$token&$query" | tr -d ' ') - queryNoToken=$(echo "package=$package-$VERSION&token=&$query" | tr -d ' ') - - if [ "$ft_s3" = "1" ]; - then - say "${e}->${x} Pinging Codecov" - say "$url/upload/v4?$queryNoToken" - # shellcheck disable=SC2086,2090 - res=$(curl $curl_s -X POST $cacert \ - --retry 5 --retry-delay 2 --connect-timeout 2 \ - -H 'X-Reduced-Redundancy: false' \ - -H 'X-Content-Type: application/x-gzip' \ - -H 'Content-Length: 0' \ - -H "X-Upload-Token: ${token}" \ - --write-out "\n%{response_code}\n" \ - $curlargs \ - "$url/upload/v4?$query" || true) - # a good reply is "https://codecov.io" + "\n" + "https://storage.googleapis.com/codecov/..." - s3target=$(echo "$res" | sed -n 2p) - status=$(tail -n1 <<< "$res") - - if [ "$status" = "200" ] && [ "$s3target" != "" ]; - then - say "${e}->${x} Uploading to" - say "${s3target}" - - # shellcheck disable=SC2086 - s3=$(curl -fiX PUT \ - --data-binary @"$upload_file.gz" \ - -H 'Content-Type: application/x-gzip' \ - -H 'Content-Encoding: gzip' \ - $curlawsargs \ - "$s3target" || true) - - if [ "$s3" != "" ]; - then - say " ${g}->${x} Reports have been successfully queued for processing at ${b}$(echo "$res" | sed -n 1p)${x}" - exit 0 - else - say " ${r}X>${x} Failed to upload" - fi - elif [ "$status" = "400" ]; - then - # 400 Error - say "${r}${res}${x}" - exit ${exit_with} - else - say "${r}${res}${x}" - fi - fi - - say "${e}==>${x} Uploading to Codecov" - - # shellcheck disable=SC2086,2090 - res=$(curl -X POST $cacert \ - --data-binary @"$upload_file.gz" \ - --retry 5 --retry-delay 2 --connect-timeout 2 \ - -H 'Content-Type: text/plain' \ - -H 'Content-Encoding: gzip' \ - -H 'X-Content-Encoding: gzip' \ - -H "X-Upload-Token: ${token}" \ - -H 'Accept: text/plain' \ - $curlargs \ - "$url/upload/v2?$query&attempt=$i" || echo 'HTTP 500') - # {"message": "Coverage reports upload successfully", "uploaded": true, "queued": true, "id": "...", "url": "https://codecov.io/..."\} - uploaded=$(grep -o '\"uploaded\": [a-z]*' <<< "$res" | head -1 | cut -d' ' -f2) - if [ "$uploaded" = "true" ] - then - say " Reports have been successfully queued for processing at ${b}$(echo "$res" | head -2 | tail -1)${x}" - exit 0 - else - say " ${g}${res}${x}" - exit ${exit_with} - fi - - say " ${r}X> Failed to upload coverage reports${x}" -fi - -exit ${exit_with} diff --git a/tools/bin/go_core_tests b/tools/bin/go_core_tests index 694a51d1f82..c0b0f43aed4 100755 --- a/tools/bin/go_core_tests +++ b/tools/bin/go_core_tests @@ -32,7 +32,5 @@ if [[ $EXITCODE != 0 ]]; then echo "Encountered test failures." else echo "All tests passed!" - # uploading coverage.txt to CodeCov - $(dirname "$0")/codecov -f coverage.txt fi exit $EXITCODE From 0a37c0ed5346df509b545c88278c026cb2adf375 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deividas=20Kar=C5=BEinauskas?= Date: Mon, 29 Apr 2024 08:32:38 +0300 Subject: [PATCH 02/45] CapabilityRegistry: add capability version (#12996) * Add capability response type and configuration contract * MUST NOT override existing capability version * MUST match configuration contract interface * Add wrappers * Include a tag to core changeset * Update ICapabilityConfiguration * Regen wrappers --- .changeset/curvy-weeks-cover.md | 5 ++ contracts/.changeset/funny-eagles-know.md | 5 ++ .../src/v0.8/keystone/CapabilityRegistry.sol | 58 +++++++++++++ .../interfaces/ICapabilityConfiguration.sol | 27 ++++++ .../src/v0.8/keystone/test/BaseTest.t.sol | 3 + ...CapabilityRegistry_AddCapabilityTest.t.sol | 82 +++++++++++++++++-- .../mocks/CapabilityConfigurationContract.sol | 13 +++ .../keystone_capability_registry.go | 10 ++- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 9 files changed, 195 insertions(+), 10 deletions(-) create mode 100644 .changeset/curvy-weeks-cover.md create mode 100644 contracts/.changeset/funny-eagles-know.md create mode 100644 contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol create mode 100644 contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol diff --git a/.changeset/curvy-weeks-cover.md b/.changeset/curvy-weeks-cover.md new file mode 100644 index 00000000000..0b19df8ad16 --- /dev/null +++ b/.changeset/curvy-weeks-cover.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#wip Keystone contract wrappers updated diff --git a/contracts/.changeset/funny-eagles-know.md b/contracts/.changeset/funny-eagles-know.md new file mode 100644 index 00000000000..46827824ad8 --- /dev/null +++ b/contracts/.changeset/funny-eagles-know.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +#wip addCapability udpates diff --git a/contracts/src/v0.8/keystone/CapabilityRegistry.sol b/contracts/src/v0.8/keystone/CapabilityRegistry.sol index faedd858bef..17f5a3dd73f 100644 --- a/contracts/src/v0.8/keystone/CapabilityRegistry.sol +++ b/contracts/src/v0.8/keystone/CapabilityRegistry.sol @@ -3,8 +3,14 @@ pragma solidity ^0.8.0; import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol"; import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; +import {IERC165} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {EnumerableSet} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; +import {ICapabilityConfiguration} from "./interfaces/ICapabilityConfiguration.sol"; contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { + // Add the library methods + using EnumerableSet for EnumerableSet.Bytes32Set; + struct NodeOperator { /// @notice The address of the admin that can manage a node /// operator @@ -13,6 +19,16 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { string name; } + // CapabilityResponseType indicates whether remote response requires + // aggregation or is an already aggregated report. There are multiple + // possible ways to aggregate. + enum CapabilityResponseType { + // No additional aggregation is needed on the remote response. + REPORT, + // A number of identical observations need to be aggregated. + OBSERVATION_IDENTICAL + } + struct Capability { // Capability type, e.g. "data-streams-reports" // bytes32(string); validation regex: ^[a-z0-9_\-:]{1,32}$ @@ -21,12 +37,39 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { // Semver, e.g., "1.2.3" // bytes32(string); must be valid Semver + max 32 characters. bytes32 version; + // responseType indicates whether remote response requires + // aggregation or is an OCR report. There are multiple possible + // ways to aggregate. + CapabilityResponseType responseType; + // An address to the capability configuration contract. Having this defined + // on a capability enforces consistent configuration across DON instances + // serving the same capability. Configuration contract MUST implement + // CapabilityConfigurationContractInterface. + // + // The main use cases are: + // 1) Sharing capability configuration across DON instances + // 2) Inspect and modify on-chain configuration without off-chain + // capability code. + // + // It is not recommended to store configuration which requires knowledge of + // the DON membership. + address configurationContract; } /// @notice This error is thrown when trying to set a node operator's /// admin address to the zero address error InvalidNodeOperatorAdmin(); + /// @notice This error is thrown when trying add a capability that already + /// exists. + error CapabilityAlreadyExists(); + + /// @notice This error is thrown when trying to add a capability with a + /// configuration contract that does not implement the required interface. + /// @param proposedConfigurationContract The address of the proposed + /// configuration contract. + error InvalidCapabilityConfigurationContractInterface(address proposedConfigurationContract); + /// @notice This event is emitted when a new node operator is added /// @param nodeOperatorId The ID of the newly added node operator /// @param admin The address of the admin that can manage the node @@ -43,6 +86,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { event CapabilityAdded(bytes32 indexed capabilityId); mapping(bytes32 => Capability) private s_capabilities; + EnumerableSet.Bytes32Set private s_capabilityIds; /// @notice Mapping of node operators mapping(uint256 nodeOperatorId => NodeOperator) private s_nodeOperators; @@ -87,7 +131,21 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { function addCapability(Capability calldata capability) external onlyOwner { bytes32 capabilityId = getCapabilityID(capability.capabilityType, capability.version); + + if (s_capabilityIds.contains(capabilityId)) revert CapabilityAlreadyExists(); + + if (capability.configurationContract != address(0)) { + if ( + capability.configurationContract.code.length == 0 || + !IERC165(capability.configurationContract).supportsInterface( + ICapabilityConfiguration.getCapabilityConfiguration.selector + ) + ) revert InvalidCapabilityConfigurationContractInterface(capability.configurationContract); + } + + s_capabilityIds.add(capabilityId); s_capabilities[capabilityId] = capability; + emit CapabilityAdded(capabilityId); } diff --git a/contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol b/contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol new file mode 100644 index 00000000000..20447c9680a --- /dev/null +++ b/contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +/// @notice Interface for capability configuration contract. It MUST be +/// implemented for a contract to be used as a capability configuration. +/// The contract MAY store configuration that is shared across multiple +/// DON instances and capability versions. +/// @dev This interface does not guarantee the configuration contract's +/// correctness. It is the responsibility of the contract owner to ensure +/// that the configuration contract emits the CapabilityConfigurationSet +/// event when the configuration is set. +interface ICapabilityConfiguration { + /// @notice Emitted when a capability configuration is set. + event CapabilityConfigurationSet(); + + /// @notice Returns the capability configuration for a particular DON instance. + /// @dev donId is required to get DON-specific configuration. It avoids a + /// situation where configuration size grows too large. + /// @param donId The DON instance ID. These are stored in the CapabilityRegistry. + /// @return configuration DON's configuration for the capability. + function getCapabilityConfiguration(uint256 donId) external view returns (bytes memory configuration); + + // Solidity does not support generic returns types, so this cannot be part of + // the interface. However, the implementation contract MAY implement this + // function to enable configuration decoding on-chain. + // function decodeCapabilityConfiguration(bytes configuration) external returns (TypedCapabilityConfigStruct config) +} diff --git a/contracts/src/v0.8/keystone/test/BaseTest.t.sol b/contracts/src/v0.8/keystone/test/BaseTest.t.sol index 5c4b4c91809..4517a256b15 100644 --- a/contracts/src/v0.8/keystone/test/BaseTest.t.sol +++ b/contracts/src/v0.8/keystone/test/BaseTest.t.sol @@ -3,14 +3,17 @@ pragma solidity ^0.8.19; import {Test} from "forge-std/Test.sol"; import {Constants} from "./Constants.t.sol"; +import {CapabilityConfigurationContract} from "./mocks/CapabilityConfigurationContract.sol"; import {CapabilityRegistry} from "../CapabilityRegistry.sol"; contract BaseTest is Test, Constants { CapabilityRegistry internal s_capabilityRegistry; + CapabilityConfigurationContract internal s_capabilityConfigurationContract; function setUp() public virtual { vm.startPrank(ADMIN); s_capabilityRegistry = new CapabilityRegistry(); + s_capabilityConfigurationContract = new CapabilityConfigurationContract(); } function _getNodeOperators() internal view returns (CapabilityRegistry.NodeOperator[] memory) { diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol index 6fbdc43a2c7..d9e4b6b8383 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol @@ -2,16 +2,88 @@ pragma solidity ^0.8.19; import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilityConfigurationContract} from "./mocks/CapabilityConfigurationContract.sol"; + import {CapabilityRegistry} from "../CapabilityRegistry.sol"; contract CapabilityRegistry_AddCapabilityTest is BaseTest { - function test_AddCapability() public { - s_capabilityRegistry.addCapability(CapabilityRegistry.Capability("data-streams-reports", "1.0.0")); + CapabilityRegistry.Capability private basicCapability = + CapabilityRegistry.Capability({ + capabilityType: "data-streams-reports", + version: "1.0.0", + responseType: CapabilityRegistry.CapabilityResponseType.REPORT, + configurationContract: address(0) + }); + + CapabilityRegistry.Capability private capabilityWithConfigurationContract = + CapabilityRegistry.Capability({ + capabilityType: "read-ethereum-mainnet-gas-price", + version: "1.0.2", + responseType: CapabilityRegistry.CapabilityResponseType.OBSERVATION_IDENTICAL, + configurationContract: address(s_capabilityConfigurationContract) + }); + + function test_RevertWhen_CalledByNonAdmin() public { + changePrank(STRANGER); + + vm.expectRevert("Only callable by owner"); + s_capabilityRegistry.addCapability(basicCapability); + } + + function test_RevertWhen_CapabilityExists() public { + // Successfully add the capability the first time + s_capabilityRegistry.addCapability(basicCapability); + + // Try to add the same capability again + vm.expectRevert(CapabilityRegistry.CapabilityAlreadyExists.selector); + s_capabilityRegistry.addCapability(basicCapability); + } + + function test_RevertWhen_ConfigurationContractNotDeployed() public { + address nonExistentContract = address(1); + capabilityWithConfigurationContract.configurationContract = nonExistentContract; + + vm.expectRevert( + abi.encodeWithSelector( + CapabilityRegistry.InvalidCapabilityConfigurationContractInterface.selector, + nonExistentContract + ) + ); + s_capabilityRegistry.addCapability(capabilityWithConfigurationContract); + } + + function test_RevertWhen_ConfigurationContractDoesNotMatchInterface() public { + CapabilityRegistry contractWithoutERC165 = new CapabilityRegistry(); + + vm.expectRevert(); + capabilityWithConfigurationContract.configurationContract = address(contractWithoutERC165); + s_capabilityRegistry.addCapability(capabilityWithConfigurationContract); + } + + function test_AddCapability_NoConfigurationContract() public { + s_capabilityRegistry.addCapability(basicCapability); bytes32 capabilityId = s_capabilityRegistry.getCapabilityID(bytes32("data-streams-reports"), bytes32("1.0.0")); - CapabilityRegistry.Capability memory capability = s_capabilityRegistry.getCapability(capabilityId); + CapabilityRegistry.Capability memory storedCapability = s_capabilityRegistry.getCapability(capabilityId); + + assertEq(storedCapability.capabilityType, basicCapability.capabilityType); + assertEq(storedCapability.version, basicCapability.version); + assertEq(uint256(storedCapability.responseType), uint256(basicCapability.responseType)); + assertEq(storedCapability.configurationContract, basicCapability.configurationContract); + } + + function test_AddCapability_WithConfiguration() public { + s_capabilityRegistry.addCapability(capabilityWithConfigurationContract); + + bytes32 capabilityId = s_capabilityRegistry.getCapabilityID( + bytes32(capabilityWithConfigurationContract.capabilityType), + bytes32(capabilityWithConfigurationContract.version) + ); + CapabilityRegistry.Capability memory storedCapability = s_capabilityRegistry.getCapability(capabilityId); - assertEq(capability.capabilityType, "data-streams-reports"); - assertEq(capability.version, "1.0.0"); + assertEq(storedCapability.capabilityType, capabilityWithConfigurationContract.capabilityType); + assertEq(storedCapability.version, capabilityWithConfigurationContract.version); + assertEq(uint256(storedCapability.responseType), uint256(capabilityWithConfigurationContract.responseType)); + assertEq(storedCapability.configurationContract, capabilityWithConfigurationContract.configurationContract); } } diff --git a/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol b/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol new file mode 100644 index 00000000000..0c3d8e0597d --- /dev/null +++ b/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ICapabilityConfiguration} from "../../interfaces/ICapabilityConfiguration.sol"; +import {ERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165.sol"; + +contract CapabilityConfigurationContract is ICapabilityConfiguration, ERC165 { + mapping(uint256 => bytes) private s_donConfiguration; + + function getCapabilityConfiguration(uint256 donId) external view returns (bytes memory configuration) { + return s_donConfiguration[donId]; + } +} diff --git a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go index 47c65d5276b..7e3ca7027eb 100644 --- a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go +++ b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go @@ -31,8 +31,10 @@ var ( ) type CapabilityRegistryCapability struct { - CapabilityType [32]byte - Version [32]byte + CapabilityType [32]byte + Version [32]byte + ResponseType uint8 + ConfigurationContract common.Address } type CapabilityRegistryNodeOperator struct { @@ -41,8 +43,8 @@ type CapabilityRegistryNodeOperator struct { } var CapabilityRegistryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityID\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b610ef1806101576000396000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80636e5f2869116100765780638da5cb5b1161005b5780638da5cb5b146101b65780639cb7c5f4146101de578063f2fde38b1461024557600080fd5b80636e5f28691461019b57806379ba5097146101ae57600080fd5b8063229111f5116100a7578063229111f514610120578063398f37731461016857806365c14dc71461017b57600080fd5b8063181f5a77146100c35780631cdf63431461010b575b600080fd5b604080518082018252601881527f4361706162696c697479526567697374727920312e302e300000000000000000602082015290516101029190610957565b60405180910390f35b61011e6101193660046109bd565b610258565b005b61015a61012e3660046109ff565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b604051908152602001610102565b61011e6101763660046109bd565b61031b565b61018e610189366004610a21565b6104b4565b6040516101029190610a3a565b61011e6101a9366004610a7d565b61059a565b61011e610617565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610102565b61022a6101ec366004610a21565b604080518082019091526000808252602082015250600090815260026020908152604091829020825180840190935280548352600101549082015290565b60408051825181526020928301519281019290925201610102565b61011e610253366004610abe565b610719565b61026061072d565b60005b8181101561031657600083838381811061027f5761027f610ad9565b60209081029290920135600081815260039093526040832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559093509190506102d060018301826108a5565b50506040518181527f1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f9060200160405180910390a15061030f81610b08565b9050610263565b505050565b61032361072d565b60005b8181101561031657600083838381811061034257610342610ad9565b90506020028101906103549190610b67565b61035d90610c4c565b805190915073ffffffffffffffffffffffffffffffffffffffff166103ae576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600454604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526003909252939020825181547fffffffffffffffffffffffff0000000000000000000000000000000000000000169216919091178155915190919060018201906104319082610db1565b5090505060046000815461044490610b08565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b9161049991859190610ecb565b60405180910390a25050806104ad90610b08565b9050610326565b6040805180820190915260008152606060208201526000828152600360209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff168352600181018054919284019161051190610d16565b80601f016020809104026020016040519081016040528092919081815260200182805461053d90610d16565b801561058a5780601f1061055f5761010080835404028352916020019161058a565b820191906000526020600020905b81548152906001019060200180831161056d57829003601f168201915b5050505050815250509050919050565b6105a261072d565b60408051823560208083018290528085013583850181905284518085038601815260609094018086528451948301949094206000818152600290935294822092835560019092019190915582917f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff069190a25050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461069d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61072161072d565b61072a816107b0565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610694565b565b3373ffffffffffffffffffffffffffffffffffffffff82160361082f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610694565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b5080546108b190610d16565b6000825580601f106108c1575050565b601f01602090049060005260206000209081019061072a91905b808211156108ef57600081556001016108db565b5090565b6000815180845260005b81811015610919576020818501810151868301820152016108fd565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061096a60208301846108f3565b9392505050565b60008083601f84011261098357600080fd5b50813567ffffffffffffffff81111561099b57600080fd5b6020830191508360208260051b85010111156109b657600080fd5b9250929050565b600080602083850312156109d057600080fd5b823567ffffffffffffffff8111156109e757600080fd5b6109f385828601610971565b90969095509350505050565b60008060408385031215610a1257600080fd5b50508035926020909101359150565b600060208284031215610a3357600080fd5b5035919050565b6020815273ffffffffffffffffffffffffffffffffffffffff825116602082015260006020830151604080840152610a7560608401826108f3565b949350505050565b600060408284031215610a8f57600080fd5b50919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610ab957600080fd5b919050565b600060208284031215610ad057600080fd5b61096a82610a95565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610b60577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112610b9b57600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610bf757610bf7610ba5565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610c4457610c44610ba5565b604052919050565b600060408236031215610c5e57600080fd5b610c66610bd4565b610c6f83610a95565b815260208084013567ffffffffffffffff80821115610c8d57600080fd5b9085019036601f830112610ca057600080fd5b813581811115610cb257610cb2610ba5565b610ce2847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610bfd565b91508082523684828501011115610cf857600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c90821680610d2a57607f821691505b602082108103610a8f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b601f82111561031657600081815260208120601f850160051c81016020861015610d8a5750805b601f850160051c820191505b81811015610da957828155600101610d96565b505050505050565b815167ffffffffffffffff811115610dcb57610dcb610ba5565b610ddf81610dd98454610d16565b84610d63565b602080601f831160018114610e325760008415610dfc5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610da9565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015610e7f57888601518255948401946001909101908401610e60565b5085821015610ebb57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b828152604060208201526000610a7560408301846108f356fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityID\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6112cb806101576000396000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c806365c14dc7116100765780638da5cb5b1161005b5780638da5cb5b1461018f5780639cb7c5f4146101b7578063f2fde38b146101d757600080fd5b806365c14dc71461016757806379ba50971461018757600080fd5b80631cdf6343116100a75780631cdf634314610120578063229111f514610133578063398f37731461015457600080fd5b8063117392ce146100c3578063181f5a77146100d8575b600080fd5b6100d66100d1366004610b88565b6101ea565b005b604080518082018252601881527f4361706162696c697479526567697374727920312e302e300000000000000000602082015290516101179190610c04565b60405180910390f35b6100d661012e366004610c63565b610420565b610146610141366004610ca5565b6104e3565b604051908152602001610117565b6100d6610162366004610c63565b610512565b61017a610175366004610cc7565b6106ab565b6040516101179190610ce0565b6100d6610791565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610117565b6101ca6101c5366004610cc7565b61088e565b6040516101179190610d52565b6100d66101e5366004610df0565b610938565b6101f261094c565b6000610203823560208401356104e3565b90506102106003826109cf565b15610247576040517fe288638f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006102596080840160608501610df0565b73ffffffffffffffffffffffffffffffffffffffff16146103c9576102846080830160608401610df0565b73ffffffffffffffffffffffffffffffffffffffff163b158061036457506102b26080830160608401610df0565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f884efe6100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff91909116906301ffc9a790602401602060405180830381865afa15801561033e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103629190610e0d565b155b156103c9576103796080830160608401610df0565b6040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024015b60405180910390fd5b6103d46003826109ea565b50600081815260026020526040902082906103ef8282610e2f565b505060405181907f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff0690600090a25050565b61042861094c565b60005b818110156104de57600083838381811061044757610447610eb1565b60209081029290920135600081815260059093526040832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559093509190506104986001830182610b3a565b50506040518181527f1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f9060200160405180910390a1506104d781610ee0565b905061042b565b505050565b604080516020808201859052818301849052825180830384018152606090920190925280519101205b92915050565b61051a61094c565b60005b818110156104de57600083838381811061053957610539610eb1565b905060200281019061054b9190610f3f565b61055490611024565b805190915073ffffffffffffffffffffffffffffffffffffffff166105a5576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600654604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526005909252939020825181547fffffffffffffffffffffffff000000000000000000000000000000000000000016921691909117815591519091906001820190610628908261118b565b5090505060066000815461063b90610ee0565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b91610690918591906112a5565b60405180910390a25050806106a490610ee0565b905061051d565b6040805180820190915260008152606060208201526000828152600560209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610708906110f0565b80601f0160208091040260200160405190810160405280929190818152602001828054610734906110f0565b80156107815780601f1061075657610100808354040283529160200191610781565b820191906000526020600020905b81548152906001019060200180831161076457829003601f168201915b5050505050815250509050919050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610812576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016103c0565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b604080516080808201835260008083526020808401829052838501829052606084018290528582526002808252918590208551938401865280548452600180820154928501929092529182015493949293919284019160ff16908111156108f7576108f7610d23565b600181111561090857610908610d23565b815260029190910154610100900473ffffffffffffffffffffffffffffffffffffffff1660209091015292915050565b61094061094c565b610949816109f6565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146109cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016103c0565b565b600081815260018301602052604081205415155b9392505050565b60006109e38383610aeb565b3373ffffffffffffffffffffffffffffffffffffffff821603610a75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016103c0565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000818152600183016020526040812054610b325750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561050c565b50600061050c565b508054610b46906110f0565b6000825580601f10610b56575050565b601f01602090049060005260206000209081019061094991905b80821115610b845760008155600101610b70565b5090565b600060808284031215610b9a57600080fd5b50919050565b6000815180845260005b81811015610bc657602081850181015186830182015201610baa565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006109e36020830184610ba0565b60008083601f840112610c2957600080fd5b50813567ffffffffffffffff811115610c4157600080fd5b6020830191508360208260051b8501011115610c5c57600080fd5b9250929050565b60008060208385031215610c7657600080fd5b823567ffffffffffffffff811115610c8d57600080fd5b610c9985828601610c17565b90969095509350505050565b60008060408385031215610cb857600080fd5b50508035926020909101359150565b600060208284031215610cd957600080fd5b5035919050565b6020815273ffffffffffffffffffffffffffffffffffffffff825116602082015260006020830151604080840152610d1b6060840182610ba0565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b81518152602080830151908201526040820151608082019060028110610da1577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8060408401525073ffffffffffffffffffffffffffffffffffffffff606084015116606083015292915050565b73ffffffffffffffffffffffffffffffffffffffff8116811461094957600080fd5b600060208284031215610e0257600080fd5b81356109e381610dce565b600060208284031215610e1f57600080fd5b815180151581146109e357600080fd5b813581556020820135600182015560028101604083013560028110610e5357600080fd5b81546060850135610e6381610dce565b74ffffffffffffffffffffffffffffffffffffffff008160081b1660ff84167fffffffffffffffffffffff000000000000000000000000000000000000000000841617178455505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610f38577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112610f7357600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610fcf57610fcf610f7d565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561101c5761101c610f7d565b604052919050565b60006040823603121561103657600080fd5b61103e610fac565b823561104981610dce565b815260208381013567ffffffffffffffff8082111561106757600080fd5b9085019036601f83011261107a57600080fd5b81358181111561108c5761108c610f7d565b6110bc847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610fd5565b915080825236848285010111156110d257600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c9082168061110457607f821691505b602082108103610b9a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b601f8211156104de57600081815260208120601f850160051c810160208610156111645750805b601f850160051c820191505b8181101561118357828155600101611170565b505050505050565b815167ffffffffffffffff8111156111a5576111a5610f7d565b6111b9816111b384546110f0565b8461113d565b602080601f83116001811461120c57600084156111d65750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555611183565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156112595788860151825594840194600190910190840161123a565b508582101561129557878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b828152604060208201526000610d1b6040830184610ba056fea164736f6c6343000813000a", } var CapabilityRegistryABI = CapabilityRegistryMetaData.ABI diff --git a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 62a75a8a644..66d26cead2d 100644 --- a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,4 +1,4 @@ GETH_VERSION: 1.13.8 forwarder: ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.bin b4c900aae9e022f01abbac7993d41f93912247613ac6270b0c4da4ef6f2016e3 -keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin 9eaa36e45c1b33c1fa72b7e25d6d1ca351413225611abb84ae053270b569cca4 +keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin d526b850decbf88dbe3dd66ed2160f1c311fb4ee6df0ac50c91f31521b361a52 ocr3_capability: ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.bin 9dcbdf55bd5729ba266148da3f17733eb592c871c2108ccca546618628fd9ad2 From 929312681fb27529915912e8bd6e4000559ea77f Mon Sep 17 00:00:00 2001 From: Christopher Dimitri Sastropranoto Date: Mon, 29 Apr 2024 18:15:28 +0700 Subject: [PATCH 03/45] Implement update node operators in capability registry (#12991) * implement update node operators in capability registry * address PR feedback * cache owner call * Validate config on NewApplication (#12997) * validate config on new application spawn * Add changeset * Check config only in the rebroadcast-transactions command * Configurable Mercury transmitter parameters (#12680) * Configurable Mercury transmitter parameters * Changeset * Remove commented code * add tag * Rename * LogPoller CLI command to resolve reorg greater than finality depth (#12867) * find lca and remove block after CLI * fix sort.Find typo * make RemoveBlocks local cmd * tests * added changeset * added tags to the changeset * fixed tests * make cmds, vars cases consistent * Fix Node Migration Test Check For Versions (#12982) * fix: prevent query syntax error if allowlist is empty (#12912) Co-authored-by: Morgan Kuphal <87319522+KuphJr@users.noreply.github.com> * Update wrappers * Formatting --------- Co-authored-by: george-dorin <120329946+george-dorin@users.noreply.github.com> Co-authored-by: Sam Co-authored-by: Dmytro Haidashenko <34754799+dhaidashenko@users.noreply.github.com> Co-authored-by: Tate Co-authored-by: Gabriel Paradiso Co-authored-by: Morgan Kuphal <87319522+KuphJr@users.noreply.github.com> Co-authored-by: DeividasK --- .changeset/early-paws-end.md | 5 + contracts/.changeset/lucky-bugs-buy.md | 5 + .../src/v0.8/keystone/CapabilityRegistry.sol | 40 +++++ ...lityRegistry_UpdateNodeOperatorsTest.t.sol | 60 +++++++ .../keystone_capability_registry.go | 159 +++++++++++++++++- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 6 files changed, 268 insertions(+), 3 deletions(-) create mode 100644 .changeset/early-paws-end.md create mode 100644 contracts/.changeset/lucky-bugs-buy.md create mode 100644 contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateNodeOperatorsTest.t.sol diff --git a/.changeset/early-paws-end.md b/.changeset/early-paws-end.md new file mode 100644 index 00000000000..1a3edb5083f --- /dev/null +++ b/.changeset/early-paws-end.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +generate gethwrappers for updating node operators in capability registry #internal diff --git a/contracts/.changeset/lucky-bugs-buy.md b/contracts/.changeset/lucky-bugs-buy.md new file mode 100644 index 00000000000..98a17d74af9 --- /dev/null +++ b/contracts/.changeset/lucky-bugs-buy.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +Add function to update node operator' diff --git a/contracts/src/v0.8/keystone/CapabilityRegistry.sol b/contracts/src/v0.8/keystone/CapabilityRegistry.sol index 17f5a3dd73f..ddf1d9b5635 100644 --- a/contracts/src/v0.8/keystone/CapabilityRegistry.sol +++ b/contracts/src/v0.8/keystone/CapabilityRegistry.sol @@ -56,6 +56,16 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { address configurationContract; } + /// @notice This error is thrown when a caller is not allowed + /// to execute the transaction + error AccessForbidden(); + + /// @notice This error is thrown when there is a mismatch between + /// array arguments + /// @param lengthOne The length of the first array argument + /// @param lengthTwo The length of the second array argument + error LengthMismatch(uint256 lengthOne, uint256 lengthTwo); + /// @notice This error is thrown when trying to set a node operator's /// admin address to the zero address error InvalidNodeOperatorAdmin(); @@ -81,6 +91,12 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @param nodeOperatorId The ID of the node operator that was removed event NodeOperatorRemoved(uint256 nodeOperatorId); + /// @notice This event is emitted when a node operator is updated + /// @param nodeOperatorId The ID of the node operator that was updated + /// @param admin The address of the node operator's admin + /// @param name The node operator's human readable name + event NodeOperatorUpdated(uint256 nodeOperatorId, address indexed admin, string name); + /// @notice This event is emitted when a new capability is added /// @param capabilityId The ID of the newly added capability event CapabilityAdded(bytes32 indexed capabilityId); @@ -122,6 +138,30 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { } } + /// @notice Updates a node operator + /// @param nodeOperatorIds The ID of the node operator being updated + function updateNodeOperators(uint256[] calldata nodeOperatorIds, NodeOperator[] calldata nodeOperators) external { + if (nodeOperatorIds.length != nodeOperators.length) + revert LengthMismatch(nodeOperatorIds.length, nodeOperators.length); + + address owner = owner(); + for (uint256 i; i < nodeOperatorIds.length; ++i) { + uint256 nodeOperatorId = nodeOperatorIds[i]; + NodeOperator memory nodeOperator = nodeOperators[i]; + if (nodeOperator.admin == address(0)) revert InvalidNodeOperatorAdmin(); + if (msg.sender != nodeOperator.admin && msg.sender != owner) revert AccessForbidden(); + + if ( + s_nodeOperators[nodeOperatorId].admin != nodeOperator.admin || + keccak256(abi.encode(s_nodeOperators[nodeOperatorId].name)) != keccak256(abi.encode(nodeOperator.name)) + ) { + s_nodeOperators[nodeOperatorId].admin = nodeOperator.admin; + s_nodeOperators[nodeOperatorId].name = nodeOperator.name; + emit NodeOperatorUpdated(nodeOperatorId, nodeOperator.admin, nodeOperator.name); + } + } + } + /// @notice Gets a node operator's data /// @param nodeOperatorId The ID of the node operator to query for /// @return NodeOperator The node operator data diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateNodeOperatorsTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateNodeOperatorsTest.t.sol new file mode 100644 index 00000000000..4be8010dcb1 --- /dev/null +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateNodeOperatorsTest.t.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilityRegistry} from "../CapabilityRegistry.sol"; + +contract CapabilityRegistry_UpdateNodeOperatorTest is BaseTest { + event NodeOperatorUpdated(uint256 nodeOperatorId, address indexed admin, string name); + + uint256 private constant TEST_NODE_OPERATOR_ID = 0; + address private constant NEW_NODE_OPERATOR_ADMIN = address(3); + string private constant NEW_NODE_OPERATOR_NAME = "new-node-operator"; + + function setUp() public override { + BaseTest.setUp(); + changePrank(ADMIN); + s_capabilityRegistry.addNodeOperators(_getNodeOperators()); + } + + function test_RevertWhen_CalledByNonAdminAndNonOwner() public { + changePrank(STRANGER); + vm.expectRevert(CapabilityRegistry.AccessForbidden.selector); + + CapabilityRegistry.NodeOperator[] memory nodeOperators = new CapabilityRegistry.NodeOperator[](1); + nodeOperators[0] = CapabilityRegistry.NodeOperator({admin: NEW_NODE_OPERATOR_ADMIN, name: NEW_NODE_OPERATOR_NAME}); + + uint256[] memory nodeOperatorIds = new uint256[](1); + nodeOperatorIds[0] = TEST_NODE_OPERATOR_ID; + s_capabilityRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); + } + + function test_RevertWhen_NodeOperatorAdminIsZeroAddress() public { + changePrank(ADMIN); + vm.expectRevert(CapabilityRegistry.InvalidNodeOperatorAdmin.selector); + CapabilityRegistry.NodeOperator[] memory nodeOperators = new CapabilityRegistry.NodeOperator[](1); + nodeOperators[0] = CapabilityRegistry.NodeOperator({admin: address(0), name: NEW_NODE_OPERATOR_NAME}); + + uint256[] memory nodeOperatorIds = new uint256[](1); + nodeOperatorIds[0] = TEST_NODE_OPERATOR_ID; + s_capabilityRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); + } + + function test_UpdatesNodeOperator() public { + changePrank(ADMIN); + + CapabilityRegistry.NodeOperator[] memory nodeOperators = new CapabilityRegistry.NodeOperator[](1); + nodeOperators[0] = CapabilityRegistry.NodeOperator({admin: NEW_NODE_OPERATOR_ADMIN, name: NEW_NODE_OPERATOR_NAME}); + + uint256[] memory nodeOperatorIds = new uint256[](1); + nodeOperatorIds[0] = TEST_NODE_OPERATOR_ID; + + vm.expectEmit(true, true, true, true, address(s_capabilityRegistry)); + emit NodeOperatorUpdated(TEST_NODE_OPERATOR_ID, NEW_NODE_OPERATOR_ADMIN, NEW_NODE_OPERATOR_NAME); + s_capabilityRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); + + CapabilityRegistry.NodeOperator memory nodeOperator = s_capabilityRegistry.getNodeOperator(0); + assertEq(nodeOperator.admin, NEW_NODE_OPERATOR_ADMIN); + assertEq(nodeOperator.name, NEW_NODE_OPERATOR_NAME); + } +} diff --git a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go index 7e3ca7027eb..61060bcb8ea 100644 --- a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go +++ b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go @@ -43,8 +43,8 @@ type CapabilityRegistryNodeOperator struct { } var CapabilityRegistryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityID\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6112cb806101576000396000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c806365c14dc7116100765780638da5cb5b1161005b5780638da5cb5b1461018f5780639cb7c5f4146101b7578063f2fde38b146101d757600080fd5b806365c14dc71461016757806379ba50971461018757600080fd5b80631cdf6343116100a75780631cdf634314610120578063229111f514610133578063398f37731461015457600080fd5b8063117392ce146100c3578063181f5a77146100d8575b600080fd5b6100d66100d1366004610b88565b6101ea565b005b604080518082018252601881527f4361706162696c697479526567697374727920312e302e300000000000000000602082015290516101179190610c04565b60405180910390f35b6100d661012e366004610c63565b610420565b610146610141366004610ca5565b6104e3565b604051908152602001610117565b6100d6610162366004610c63565b610512565b61017a610175366004610cc7565b6106ab565b6040516101179190610ce0565b6100d6610791565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610117565b6101ca6101c5366004610cc7565b61088e565b6040516101179190610d52565b6100d66101e5366004610df0565b610938565b6101f261094c565b6000610203823560208401356104e3565b90506102106003826109cf565b15610247576040517fe288638f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006102596080840160608501610df0565b73ffffffffffffffffffffffffffffffffffffffff16146103c9576102846080830160608401610df0565b73ffffffffffffffffffffffffffffffffffffffff163b158061036457506102b26080830160608401610df0565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f884efe6100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff91909116906301ffc9a790602401602060405180830381865afa15801561033e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103629190610e0d565b155b156103c9576103796080830160608401610df0565b6040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024015b60405180910390fd5b6103d46003826109ea565b50600081815260026020526040902082906103ef8282610e2f565b505060405181907f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff0690600090a25050565b61042861094c565b60005b818110156104de57600083838381811061044757610447610eb1565b60209081029290920135600081815260059093526040832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559093509190506104986001830182610b3a565b50506040518181527f1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f9060200160405180910390a1506104d781610ee0565b905061042b565b505050565b604080516020808201859052818301849052825180830384018152606090920190925280519101205b92915050565b61051a61094c565b60005b818110156104de57600083838381811061053957610539610eb1565b905060200281019061054b9190610f3f565b61055490611024565b805190915073ffffffffffffffffffffffffffffffffffffffff166105a5576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600654604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526005909252939020825181547fffffffffffffffffffffffff000000000000000000000000000000000000000016921691909117815591519091906001820190610628908261118b565b5090505060066000815461063b90610ee0565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b91610690918591906112a5565b60405180910390a25050806106a490610ee0565b905061051d565b6040805180820190915260008152606060208201526000828152600560209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610708906110f0565b80601f0160208091040260200160405190810160405280929190818152602001828054610734906110f0565b80156107815780601f1061075657610100808354040283529160200191610781565b820191906000526020600020905b81548152906001019060200180831161076457829003601f168201915b5050505050815250509050919050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610812576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016103c0565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b604080516080808201835260008083526020808401829052838501829052606084018290528582526002808252918590208551938401865280548452600180820154928501929092529182015493949293919284019160ff16908111156108f7576108f7610d23565b600181111561090857610908610d23565b815260029190910154610100900473ffffffffffffffffffffffffffffffffffffffff1660209091015292915050565b61094061094c565b610949816109f6565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146109cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016103c0565b565b600081815260018301602052604081205415155b9392505050565b60006109e38383610aeb565b3373ffffffffffffffffffffffffffffffffffffffff821603610a75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016103c0565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000818152600183016020526040812054610b325750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561050c565b50600061050c565b508054610b46906110f0565b6000825580601f10610b56575050565b601f01602090049060005260206000209081019061094991905b80821115610b845760008155600101610b70565b5090565b600060808284031215610b9a57600080fd5b50919050565b6000815180845260005b81811015610bc657602081850181015186830182015201610baa565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006109e36020830184610ba0565b60008083601f840112610c2957600080fd5b50813567ffffffffffffffff811115610c4157600080fd5b6020830191508360208260051b8501011115610c5c57600080fd5b9250929050565b60008060208385031215610c7657600080fd5b823567ffffffffffffffff811115610c8d57600080fd5b610c9985828601610c17565b90969095509350505050565b60008060408385031215610cb857600080fd5b50508035926020909101359150565b600060208284031215610cd957600080fd5b5035919050565b6020815273ffffffffffffffffffffffffffffffffffffffff825116602082015260006020830151604080840152610d1b6060840182610ba0565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b81518152602080830151908201526040820151608082019060028110610da1577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8060408401525073ffffffffffffffffffffffffffffffffffffffff606084015116606083015292915050565b73ffffffffffffffffffffffffffffffffffffffff8116811461094957600080fd5b600060208284031215610e0257600080fd5b81356109e381610dce565b600060208284031215610e1f57600080fd5b815180151581146109e357600080fd5b813581556020820135600182015560028101604083013560028110610e5357600080fd5b81546060850135610e6381610dce565b74ffffffffffffffffffffffffffffffffffffffff008160081b1660ff84167fffffffffffffffffffffff000000000000000000000000000000000000000000841617178455505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610f38577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112610f7357600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610fcf57610fcf610f7d565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561101c5761101c610f7d565b604052919050565b60006040823603121561103657600080fd5b61103e610fac565b823561104981610dce565b815260208381013567ffffffffffffffff8082111561106757600080fd5b9085019036601f83011261107a57600080fd5b81358181111561108c5761108c610f7d565b6110bc847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610fd5565b915080825236848285010111156110d257600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c9082168061110457607f821691505b602082108103610b9a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b601f8211156104de57600081815260208120601f850160051c810160208610156111645750805b601f850160051c820191505b8181101561118357828155600101611170565b505050505050565b815167ffffffffffffffff8111156111a5576111a5610f7d565b6111b9816111b384546110f0565b8461113d565b602080601f83116001811461120c57600084156111d65750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555611183565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156112595788860151825594840194600190910190840161123a565b508582101561129557878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b828152604060208201526000610d1b6040830184610ba056fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"lengthOne\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lengthTwo\",\"type\":\"uint256\"}],\"name\":\"LengthMismatch\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityID\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"updateNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611702806101576000396000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c8063398f3773116100815780638da5cb5b1161005b5780638da5cb5b146101ad5780639cb7c5f4146101d5578063f2fde38b146101f557600080fd5b8063398f37731461017257806365c14dc71461018557806379ba5097146101a557600080fd5b8063181f5a77116100b2578063181f5a77146100f65780631cdf63431461013e578063229111f51461015157600080fd5b80630c5801e3146100ce578063117392ce146100e3575b600080fd5b6100e16100dc366004610efe565b610208565b005b6100e16100f1366004610f6a565b610519565b604080518082018252601881527f4361706162696c697479526567697374727920312e302e300000000000000000602082015290516101359190610fe6565b60405180910390f35b6100e161014c366004610ff9565b61074a565b61016461015f36600461103b565b61080d565b604051908152602001610135565b6100e1610180366004610ff9565b61083c565b61019861019336600461105d565b6109d5565b6040516101359190611076565b6100e1610abb565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610135565b6101e86101e336600461105d565b610bb8565b60405161013591906110e8565b6100e1610203366004611186565b610c62565b828114610250576040517fab8b67c600000000000000000000000000000000000000000000000000000000815260048101849052602481018290526044015b60405180910390fd5b6000805473ffffffffffffffffffffffffffffffffffffffff16905b84811015610511576000868683818110610288576102886111a3565b90506020020135905060008585848181106102a5576102a56111a3565b90506020028101906102b791906111d2565b6102c0906112b7565b805190915073ffffffffffffffffffffffffffffffffffffffff16610311576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16331480159061034e57503373ffffffffffffffffffffffffffffffffffffffff851614155b15610385576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160008381526005602052604090205473ffffffffffffffffffffffffffffffffffffffff908116911614158061043757506020808201516040516103cb9201610fe6565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012060008681526005835292909220919261041e9260010191016113d0565b6040516020818303038152906040528051906020012014155b156104fe578051600083815260056020908152604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921782558201516001909101906104a490826114bf565b50806000015173ffffffffffffffffffffffffffffffffffffffff167f14c8f513e8a6d86d2d16b0cb64976de4e72386c4f8068eca3b7354373f8fe97a8383602001516040516104f59291906115d9565b60405180910390a25b50508061050a906115f2565b905061026c565b505050505050565b610521610c76565b60006105328235602084013561080d565b905061053f600382610cf9565b15610576576040517fe288638f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105886080840160608501611186565b73ffffffffffffffffffffffffffffffffffffffff16146106f3576105b36080830160608401611186565b73ffffffffffffffffffffffffffffffffffffffff163b158061069357506105e16080830160608401611186565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f884efe6100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff91909116906301ffc9a790602401602060405180830381865afa15801561066d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106919190611651565b155b156106f3576106a86080830160608401611186565b6040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610247565b6106fe600382610d14565b50600081815260026020526040902082906107198282611673565b505060405181907f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff0690600090a25050565b610752610c76565b60005b81811015610808576000838383818110610771576107716111a3565b60209081029290920135600081815260059093526040832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559093509190506107c26001830182610e64565b50506040518181527f1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f9060200160405180910390a150610801816115f2565b9050610755565b505050565b604080516020808201859052818301849052825180830384018152606090920190925280519101205b92915050565b610844610c76565b60005b81811015610808576000838383818110610863576108636111a3565b905060200281019061087591906111d2565b61087e906112b7565b805190915073ffffffffffffffffffffffffffffffffffffffff166108cf576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600654604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526005909252939020825181547fffffffffffffffffffffffff00000000000000000000000000000000000000001692169190911781559151909190600182019061095290826114bf565b50905050600660008154610965906115f2565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b916109ba918591906115d9565b60405180910390a25050806109ce906115f2565b9050610847565b6040805180820190915260008152606060208201526000828152600560209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610a3290611383565b80601f0160208091040260200160405190810160405280929190818152602001828054610a5e90611383565b8015610aab5780601f10610a8057610100808354040283529160200191610aab565b820191906000526020600020905b815481529060010190602001808311610a8e57829003601f168201915b5050505050815250509050919050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610b3c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610247565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b604080516080808201835260008083526020808401829052838501829052606084018290528582526002808252918590208551938401865280548452600180820154928501929092529182015493949293919284019160ff1690811115610c2157610c216110b9565b6001811115610c3257610c326110b9565b815260029190910154610100900473ffffffffffffffffffffffffffffffffffffffff1660209091015292915050565b610c6a610c76565b610c7381610d20565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610cf7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610247565b565b600081815260018301602052604081205415155b9392505050565b6000610d0d8383610e15565b3373ffffffffffffffffffffffffffffffffffffffff821603610d9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610247565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000818152600183016020526040812054610e5c57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610836565b506000610836565b508054610e7090611383565b6000825580601f10610e80575050565b601f016020900490600052602060002090810190610c7391905b80821115610eae5760008155600101610e9a565b5090565b60008083601f840112610ec457600080fd5b50813567ffffffffffffffff811115610edc57600080fd5b6020830191508360208260051b8501011115610ef757600080fd5b9250929050565b60008060008060408587031215610f1457600080fd5b843567ffffffffffffffff80821115610f2c57600080fd5b610f3888838901610eb2565b90965094506020870135915080821115610f5157600080fd5b50610f5e87828801610eb2565b95989497509550505050565b600060808284031215610f7c57600080fd5b50919050565b6000815180845260005b81811015610fa857602081850181015186830182015201610f8c565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610d0d6020830184610f82565b6000806020838503121561100c57600080fd5b823567ffffffffffffffff81111561102357600080fd5b61102f85828601610eb2565b90969095509350505050565b6000806040838503121561104e57600080fd5b50508035926020909101359150565b60006020828403121561106f57600080fd5b5035919050565b6020815273ffffffffffffffffffffffffffffffffffffffff8251166020820152600060208301516040808401526110b16060840182610f82565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b81518152602080830151908201526040820151608082019060028110611137577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8060408401525073ffffffffffffffffffffffffffffffffffffffff606084015116606083015292915050565b73ffffffffffffffffffffffffffffffffffffffff81168114610c7357600080fd5b60006020828403121561119857600080fd5b8135610d0d81611164565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261120657600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561126257611262611210565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156112af576112af611210565b604052919050565b6000604082360312156112c957600080fd5b6112d161123f565b82356112dc81611164565b815260208381013567ffffffffffffffff808211156112fa57600080fd5b9085019036601f83011261130d57600080fd5b81358181111561131f5761131f611210565b61134f847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611268565b9150808252368482850101111561136557600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c9082168061139757607f821691505b602082108103610f7c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006020808352600084546113e481611383565b80848701526040600180841660008114611405576001811461143d5761146b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a0101955061146b565b896000528660002060005b858110156114635781548b8201860152908301908801611448565b8a0184019650505b509398975050505050505050565b601f82111561080857600081815260208120601f850160051c810160208610156114a05750805b601f850160051c820191505b81811015610511578281556001016114ac565b815167ffffffffffffffff8111156114d9576114d9611210565b6114ed816114e78454611383565b84611479565b602080601f831160018114611540576000841561150a5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610511565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561158d5788860151825594840194600190910190840161156e565b50858210156115c957878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8281526040602082015260006110b16040830184610f82565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361164a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b60006020828403121561166357600080fd5b81518015158114610d0d57600080fd5b81358155602082013560018201556002810160408301356002811061169757600080fd5b815460608501356116a781611164565b74ffffffffffffffffffffffffffffffffffffffff008160081b1660ff84167fffffffffffffffffffffff00000000000000000000000000000000000000000084161717845550505050505056fea164736f6c6343000813000a", } var CapabilityRegistryABI = CapabilityRegistryMetaData.ABI @@ -353,6 +353,18 @@ func (_CapabilityRegistry *CapabilityRegistryTransactorSession) TransferOwnershi return _CapabilityRegistry.Contract.TransferOwnership(&_CapabilityRegistry.TransactOpts, to) } +func (_CapabilityRegistry *CapabilityRegistryTransactor) UpdateNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []*big.Int, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) { + return _CapabilityRegistry.contract.Transact(opts, "updateNodeOperators", nodeOperatorIds, nodeOperators) +} + +func (_CapabilityRegistry *CapabilityRegistrySession) UpdateNodeOperators(nodeOperatorIds []*big.Int, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.UpdateNodeOperators(&_CapabilityRegistry.TransactOpts, nodeOperatorIds, nodeOperators) +} + +func (_CapabilityRegistry *CapabilityRegistryTransactorSession) UpdateNodeOperators(nodeOperatorIds []*big.Int, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.UpdateNodeOperators(&_CapabilityRegistry.TransactOpts, nodeOperatorIds, nodeOperators) +} + type CapabilityRegistryCapabilityAddedIterator struct { Event *CapabilityRegistryCapabilityAdded @@ -726,6 +738,135 @@ func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseNodeOperatorRemoved( return event, nil } +type CapabilityRegistryNodeOperatorUpdatedIterator struct { + Event *CapabilityRegistryNodeOperatorUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilityRegistryNodeOperatorUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryNodeOperatorUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryNodeOperatorUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CapabilityRegistryNodeOperatorUpdatedIterator) Error() error { + return it.fail +} + +func (it *CapabilityRegistryNodeOperatorUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilityRegistryNodeOperatorUpdated struct { + NodeOperatorId *big.Int + Admin common.Address + Name string + Raw types.Log +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterNodeOperatorUpdated(opts *bind.FilterOpts, admin []common.Address) (*CapabilityRegistryNodeOperatorUpdatedIterator, error) { + + var adminRule []interface{} + for _, adminItem := range admin { + adminRule = append(adminRule, adminItem) + } + + logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "NodeOperatorUpdated", adminRule) + if err != nil { + return nil, err + } + return &CapabilityRegistryNodeOperatorUpdatedIterator{contract: _CapabilityRegistry.contract, event: "NodeOperatorUpdated", logs: logs, sub: sub}, nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchNodeOperatorUpdated(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeOperatorUpdated, admin []common.Address) (event.Subscription, error) { + + var adminRule []interface{} + for _, adminItem := range admin { + adminRule = append(adminRule, adminItem) + } + + logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "NodeOperatorUpdated", adminRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilityRegistryNodeOperatorUpdated) + if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeOperatorUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseNodeOperatorUpdated(log types.Log) (*CapabilityRegistryNodeOperatorUpdated, error) { + event := new(CapabilityRegistryNodeOperatorUpdated) + if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeOperatorUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type CapabilityRegistryOwnershipTransferRequestedIterator struct { Event *CapabilityRegistryOwnershipTransferRequested @@ -1006,6 +1147,8 @@ func (_CapabilityRegistry *CapabilityRegistry) ParseLog(log types.Log) (generate return _CapabilityRegistry.ParseNodeOperatorAdded(log) case _CapabilityRegistry.abi.Events["NodeOperatorRemoved"].ID: return _CapabilityRegistry.ParseNodeOperatorRemoved(log) + case _CapabilityRegistry.abi.Events["NodeOperatorUpdated"].ID: + return _CapabilityRegistry.ParseNodeOperatorUpdated(log) case _CapabilityRegistry.abi.Events["OwnershipTransferRequested"].ID: return _CapabilityRegistry.ParseOwnershipTransferRequested(log) case _CapabilityRegistry.abi.Events["OwnershipTransferred"].ID: @@ -1028,6 +1171,10 @@ func (CapabilityRegistryNodeOperatorRemoved) Topic() common.Hash { return common.HexToHash("0x1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f") } +func (CapabilityRegistryNodeOperatorUpdated) Topic() common.Hash { + return common.HexToHash("0x14c8f513e8a6d86d2d16b0cb64976de4e72386c4f8068eca3b7354373f8fe97a") +} + func (CapabilityRegistryOwnershipTransferRequested) Topic() common.Hash { return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") } @@ -1061,6 +1208,8 @@ type CapabilityRegistryInterface interface { TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + UpdateNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []*big.Int, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) + FilterCapabilityAdded(opts *bind.FilterOpts, capabilityId [][32]byte) (*CapabilityRegistryCapabilityAddedIterator, error) WatchCapabilityAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityAdded, capabilityId [][32]byte) (event.Subscription, error) @@ -1079,6 +1228,12 @@ type CapabilityRegistryInterface interface { ParseNodeOperatorRemoved(log types.Log) (*CapabilityRegistryNodeOperatorRemoved, error) + FilterNodeOperatorUpdated(opts *bind.FilterOpts, admin []common.Address) (*CapabilityRegistryNodeOperatorUpdatedIterator, error) + + WatchNodeOperatorUpdated(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeOperatorUpdated, admin []common.Address) (event.Subscription, error) + + ParseNodeOperatorUpdated(log types.Log) (*CapabilityRegistryNodeOperatorUpdated, error) + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilityRegistryOwnershipTransferRequestedIterator, error) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) diff --git a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 66d26cead2d..e137d35ea5e 100644 --- a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,4 +1,4 @@ GETH_VERSION: 1.13.8 forwarder: ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.bin b4c900aae9e022f01abbac7993d41f93912247613ac6270b0c4da4ef6f2016e3 -keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin d526b850decbf88dbe3dd66ed2160f1c311fb4ee6df0ac50c91f31521b361a52 +keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin 5f801185084a6d6bcc08e0a37574d80f5092bc0dcd40808e9e04804064db0a56 ocr3_capability: ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.bin 9dcbdf55bd5729ba266148da3f17733eb592c871c2108ccca546618628fd9ad2 From c97781582bbe0333332b985fb10a06edeaafa524 Mon Sep 17 00:00:00 2001 From: Dimitris Grigoriou Date: Mon, 29 Apr 2024 15:25:33 +0300 Subject: [PATCH 04/45] Transfer testutils (#12968) * Add first version of evm utils * Remove unused context util * Add WSServer tests * Add NewLegacyTransaction test * Update NewTestChainScopedConfig to apply correct defaults * Move testutils * Fix lint * Add changeset --- .changeset/fresh-rice-learn.md | 5 + core/chains/evm/testutils/client.go | 198 +++++++++++++++++++++++ core/chains/evm/testutils/config.go | 29 ++++ core/chains/evm/testutils/config_test.go | 22 +++ core/chains/evm/testutils/evmtypes.go | 76 +++++++++ core/chains/evm/testutils/timeout.go | 41 +++++ 6 files changed, 371 insertions(+) create mode 100644 .changeset/fresh-rice-learn.md create mode 100644 core/chains/evm/testutils/client.go create mode 100644 core/chains/evm/testutils/config.go create mode 100644 core/chains/evm/testutils/config_test.go create mode 100644 core/chains/evm/testutils/evmtypes.go create mode 100644 core/chains/evm/testutils/timeout.go diff --git a/.changeset/fresh-rice-learn.md b/.changeset/fresh-rice-learn.md new file mode 100644 index 00000000000..6425cdd4581 --- /dev/null +++ b/.changeset/fresh-rice-learn.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Moved test functions under evm package to support evm extraction #internal diff --git a/core/chains/evm/testutils/client.go b/core/chains/evm/testutils/client.go new file mode 100644 index 00000000000..31ad23eeb81 --- /dev/null +++ b/core/chains/evm/testutils/client.go @@ -0,0 +1,198 @@ +package testutils + +import ( + "fmt" + "math/big" + "net/http" + "net/http/httptest" + "net/url" + "sync" + "testing" + "time" + + "github.com/gorilla/websocket" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/tidwall/gjson" + + evmclmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" +) + +func NewEthClientMock(t *testing.T) *evmclmocks.Client { + return evmclmocks.NewClient(t) +} + +func NewEthClientMockWithDefaultChain(t *testing.T) *evmclmocks.Client { + c := NewEthClientMock(t) + c.On("ConfiguredChainID").Return(FixtureChainID).Maybe() + //c.On("IsL2").Return(false).Maybe() + return c +} + +// JSONRPCHandler is called with the method and request param(s). +// respResult will be sent immediately. notifyResult is optional, and sent after a short delay. +type JSONRPCHandler func(reqMethod string, reqParams gjson.Result) JSONRPCResponse + +type JSONRPCResponse struct { + Result, Notify string // raw JSON (i.e. quoted strings etc.) + + Error struct { + Code int + Message string + } +} + +type testWSServer struct { + t *testing.T + s *httptest.Server + mu sync.RWMutex + wsconns []*websocket.Conn + wg sync.WaitGroup +} + +// NewWSServer starts a websocket server which invokes callback for each message received. +// If chainID is set, then eth_chainId calls will be automatically handled. +func NewWSServer(t *testing.T, chainID *big.Int, callback JSONRPCHandler) (ts *testWSServer) { + ts = new(testWSServer) + ts.t = t + ts.wsconns = make([]*websocket.Conn, 0) + handler := ts.newWSHandler(chainID, callback) + ts.s = httptest.NewServer(handler) + t.Cleanup(ts.Close) + return +} + +func (ts *testWSServer) Close() { + if func() bool { + ts.mu.Lock() + defer ts.mu.Unlock() + if ts.wsconns == nil { + ts.t.Log("Test WS server already closed") + return false + } + ts.s.CloseClientConnections() + ts.s.Close() + for _, ws := range ts.wsconns { + ws.Close() + } + ts.wsconns = nil // nil indicates server closed + return true + }() { + ts.wg.Wait() + } +} + +func (ts *testWSServer) WSURL() *url.URL { + return WSServerURL(ts.t, ts.s) +} + +// WSServerURL returns a ws:// url for the server +func WSServerURL(t *testing.T, s *httptest.Server) *url.URL { + u, err := url.Parse(s.URL) + require.NoError(t, err, "Failed to parse url") + u.Scheme = "ws" + return u +} + +func (ts *testWSServer) MustWriteBinaryMessageSync(t *testing.T, msg string) { + ts.mu.Lock() + defer ts.mu.Unlock() + conns := ts.wsconns + if len(conns) != 1 { + t.Fatalf("expected 1 conn, got %d", len(conns)) + } + conn := conns[0] + err := conn.WriteMessage(websocket.BinaryMessage, []byte(msg)) + require.NoError(t, err) +} + +func (ts *testWSServer) newWSHandler(chainID *big.Int, callback JSONRPCHandler) (handler http.HandlerFunc) { + if callback == nil { + callback = func(method string, params gjson.Result) (resp JSONRPCResponse) { return } + } + t := ts.t + upgrader := websocket.Upgrader{ + CheckOrigin: func(r *http.Request) bool { return true }, + } + return func(w http.ResponseWriter, r *http.Request) { + ts.mu.Lock() + if ts.wsconns == nil { // closed + ts.mu.Unlock() + return + } + ts.wg.Add(1) + defer ts.wg.Done() + conn, err := upgrader.Upgrade(w, r, nil) + if !assert.NoError(t, err, "Failed to upgrade WS connection") { + ts.mu.Unlock() + return + } + defer conn.Close() + ts.wsconns = append(ts.wsconns, conn) + ts.mu.Unlock() + + for { + _, data, err := conn.ReadMessage() + if err != nil { + if websocket.IsCloseError(err, websocket.CloseNormalClosure, websocket.CloseAbnormalClosure) { + ts.t.Log("Websocket closing") + return + } + ts.t.Logf("Failed to read message: %v", err) + return + } + ts.t.Log("Received message", string(data)) + req := gjson.ParseBytes(data) + if !req.IsObject() { + ts.t.Logf("Request must be object: %v", req.Type) + return + } + if e := req.Get("error"); e.Exists() { + ts.t.Logf("Received jsonrpc error: %v", e) + continue + } + m := req.Get("method") + if m.Type != gjson.String { + ts.t.Logf("Method must be string: %v", m.Type) + return + } + + var resp JSONRPCResponse + if chainID != nil && m.String() == "eth_chainId" { + resp.Result = `"0x` + chainID.Text(16) + `"` + } else if m.String() == "eth_syncing" { + resp.Result = "false" + } else { + resp = callback(m.String(), req.Get("params")) + } + id := req.Get("id") + var msg string + if resp.Error.Message != "" { + msg = fmt.Sprintf(`{"jsonrpc":"2.0","id":%s,"error":{"code":%d,"message":"%s"}}`, id, resp.Error.Code, resp.Error.Message) + } else { + msg = fmt.Sprintf(`{"jsonrpc":"2.0","id":%s,"result":%s}`, id, resp.Result) + } + ts.t.Logf("Sending message: %v", msg) + ts.mu.Lock() + err = conn.WriteMessage(websocket.BinaryMessage, []byte(msg)) + ts.mu.Unlock() + if err != nil { + ts.t.Logf("Failed to write message: %v", err) + return + } + + if resp.Notify != "" { + time.Sleep(100 * time.Millisecond) + msg := fmt.Sprintf(`{"jsonrpc":"2.0","method":"eth_subscription","params":{"subscription":"0x00","result":%s}}`, resp.Notify) + ts.t.Log("Sending message", msg) + ts.mu.Lock() + err = conn.WriteMessage(websocket.BinaryMessage, []byte(msg)) + ts.mu.Unlock() + if err != nil { + ts.t.Logf("Failed to write message: %v", err) + return + } + } + } + } +} diff --git a/core/chains/evm/testutils/config.go b/core/chains/evm/testutils/config.go new file mode 100644 index 00000000000..3d1425c5333 --- /dev/null +++ b/core/chains/evm/testutils/config.go @@ -0,0 +1,29 @@ +package testutils + +import ( + "testing" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" +) + +func NewTestChainScopedConfig(t testing.TB, overrideFn func(c *toml.EVMConfig)) config.ChainScopedConfig { + var chainID = (*big.Big)(FixtureChainID) + evmCfg := &toml.EVMConfig{ + ChainID: chainID, + Chain: toml.Defaults(chainID), + } + + if overrideFn != nil { + // We need to get the chainID from the override function first to load the correct chain defaults. + // Then we apply the override values on top + overrideFn(evmCfg) + evmCfg.Chain = toml.Defaults(evmCfg.ChainID) + overrideFn(evmCfg) + } + + return config.NewTOMLChainScopedConfig(evmCfg, logger.Test(t)) +} diff --git a/core/chains/evm/testutils/config_test.go b/core/chains/evm/testutils/config_test.go new file mode 100644 index 00000000000..0cbcc5eb63b --- /dev/null +++ b/core/chains/evm/testutils/config_test.go @@ -0,0 +1,22 @@ +package testutils + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" +) + +func TestNewTestChainScopedConfigOverride(t *testing.T) { + c := NewTestChainScopedConfig(t, func(c *toml.EVMConfig) { + finalityDepth := uint32(100) + c.FinalityDepth = &finalityDepth + }) + + // Overrides values + assert.Equal(t, uint32(100), c.EVM().FinalityDepth()) + // fallback.toml values + assert.Equal(t, false, c.EVM().GasEstimator().EIP1559DynamicFees()) + +} diff --git a/core/chains/evm/testutils/evmtypes.go b/core/chains/evm/testutils/evmtypes.go new file mode 100644 index 00000000000..5f9ae83d1b7 --- /dev/null +++ b/core/chains/evm/testutils/evmtypes.go @@ -0,0 +1,76 @@ +package testutils + +import ( + "crypto/rand" + "fmt" + "math" + "math/big" + mrand "math/rand" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" +) + +// FixtureChainID matches the chain always added by fixtures.sql +// It is set to 0 since no real chain ever has this ID and allows a virtual +// "test" chain ID to be used without clashes +var FixtureChainID = big.NewInt(0) + +// SimulatedChainID is the chain ID for the go-ethereum simulated backend +var SimulatedChainID = big.NewInt(1337) + +// NewRandomEVMChainID returns a suitable random chain ID that will not conflict +// with fixtures +func NewRandomEVMChainID() *big.Int { + id := mrand.Int63n(math.MaxInt32) + 10000 + return big.NewInt(id) +} + +// NewAddress return a random new address +func NewAddress() common.Address { + return common.BytesToAddress(randomBytes(20)) +} + +func randomBytes(n int) []byte { + b := make([]byte, n) + _, err := rand.Read(b) + if err != nil { + panic(err) + } + return b +} + +// Head given the value convert it into an Head +func Head(val interface{}) *evmtypes.Head { + var h evmtypes.Head + time := uint64(0) + switch t := val.(type) { + case int: + h = evmtypes.NewHead(big.NewInt(int64(t)), evmutils.NewHash(), evmutils.NewHash(), time, ubig.New(FixtureChainID)) + case uint64: + h = evmtypes.NewHead(big.NewInt(int64(t)), evmutils.NewHash(), evmutils.NewHash(), time, ubig.New(FixtureChainID)) + case int64: + h = evmtypes.NewHead(big.NewInt(t), evmutils.NewHash(), evmutils.NewHash(), time, ubig.New(FixtureChainID)) + case *big.Int: + h = evmtypes.NewHead(t, evmutils.NewHash(), evmutils.NewHash(), time, ubig.New(FixtureChainID)) + default: + panic(fmt.Sprintf("Could not convert %v of type %T to Head", val, val)) + } + return &h +} + +func NewLegacyTransaction(nonce uint64, to common.Address, value *big.Int, gasLimit uint32, gasPrice *big.Int, data []byte) *types.Transaction { + tx := types.LegacyTx{ + Nonce: nonce, + To: &to, + Value: value, + Gas: uint64(gasLimit), + GasPrice: gasPrice, + Data: data, + } + return types.NewTx(&tx) +} diff --git a/core/chains/evm/testutils/timeout.go b/core/chains/evm/testutils/timeout.go new file mode 100644 index 00000000000..4c7864f1191 --- /dev/null +++ b/core/chains/evm/testutils/timeout.go @@ -0,0 +1,41 @@ +package testutils + +import ( + "testing" + "time" +) + +type Awaiter chan struct{} + +func NewAwaiter() Awaiter { return make(Awaiter) } + +func (a Awaiter) ItHappened() { close(a) } + +func (a Awaiter) AssertHappened(t *testing.T, expected bool) { + t.Helper() + select { + case <-a: + if !expected { + t.Fatal("It happened") + } + default: + if expected { + t.Fatal("It didn't happen") + } + } +} + +func (a Awaiter) AwaitOrFail(t testing.TB, durationParams ...time.Duration) { + t.Helper() + + duration := 10 * time.Second + if len(durationParams) > 0 { + duration = durationParams[0] + } + + select { + case <-a: + case <-time.After(duration): + t.Fatal("Timed out waiting for Awaiter to get ItHappened") + } +} From 1b994043b00cad9e0c900b6d12173dd1008480a5 Mon Sep 17 00:00:00 2001 From: Matthew Pendrey Date: Mon, 29 Apr 2024 16:16:07 +0100 Subject: [PATCH 05/45] =?UTF-8?q?BCF-3168:=20changes=20required=20to=20int?= =?UTF-8?q?egrate=20with=20the=20RelayerSet=20from=20chai=E2=80=A6=20(#130?= =?UTF-8?q?00)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * BCF-3168: changes required to integrate with the RelayerSet from chainlink common * lint * lint * goimports --- .changeset/beige-socks-cover.md | 5 + core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 +- .../mocks/relayer_chain_interoperators.go | 4 + .../chainlink/relayer_chain_interoperators.go | 13 +- core/services/chainlink/relayer_factory.go | 2 +- core/services/job/spawner_test.go | 4 + core/services/ocr2/delegate.go | 29 +-- .../ocr2/plugins/generic/relayerset.go | 87 ++++++++ .../ocr2/plugins/generic/relayerset_test.go | 173 ++++++++++++++++ core/services/ocrbootstrap/delegate.go | 1 + core/services/relay/evm/loop_impl.go | 2 +- core/services/relay/evm/relayer_extender.go | 4 +- core/services/relay/grpc_provider_server.go | 68 ------- .../relay/grpc_provider_server_test.go | 28 --- core/services/relay/relay.go | 38 ---- core/services/relay/relay_test.go | 191 ------------------ go.mod | 2 +- go.sum | 4 +- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 +- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 +- plugins/medianpoc/plugin.go | 1 + 24 files changed, 318 insertions(+), 356 deletions(-) create mode 100644 .changeset/beige-socks-cover.md create mode 100644 core/services/ocr2/plugins/generic/relayerset.go create mode 100644 core/services/ocr2/plugins/generic/relayerset_test.go delete mode 100644 core/services/relay/grpc_provider_server.go delete mode 100644 core/services/relay/grpc_provider_server_test.go delete mode 100644 core/services/relay/relay.go delete mode 100644 core/services/relay/relay_test.go diff --git a/.changeset/beige-socks-cover.md b/.changeset/beige-socks-cover.md new file mode 100644 index 00000000000..0b7c22d01e5 --- /dev/null +++ b/.changeset/beige-socks-cover.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#internal changes to core required by change BCF3168 in common to add relayer set diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 08050c32167..3963538b2c3 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -21,7 +21,7 @@ require ( github.com/prometheus/client_golang v1.17.0 github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 48a66de1ec3..daedbe64eb3 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1185,8 +1185,8 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 h1:54hM3/SrOM166it2K35hGb5K7gQ49/Op0aHp9WkqpqU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb h1:nJ9dkgvX5vdpFWhYufnRUAiNvNHsXkoBL6C0bDerq/k= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee h1:eFuBKyEbL2b+eyfgV/Eu9+8HuCEev+IcBi+K9l1dG7g= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/core/services/chainlink/mocks/relayer_chain_interoperators.go b/core/services/chainlink/mocks/relayer_chain_interoperators.go index 6e47f6a1f9b..5b0815b6569 100644 --- a/core/services/chainlink/mocks/relayer_chain_interoperators.go +++ b/core/services/chainlink/mocks/relayer_chain_interoperators.go @@ -43,6 +43,10 @@ func (f *FakeRelayerChainInteroperators) Get(id types.RelayID) (loop.Relayer, er panic("unimplemented") } +func (f *FakeRelayerChainInteroperators) GetIDToRelayerMap() (map[types.RelayID]loop.Relayer, error) { + panic("unimplemented") +} + func (f *FakeRelayerChainInteroperators) Slice() []loop.Relayer { return f.Relayers } diff --git a/core/services/chainlink/relayer_chain_interoperators.go b/core/services/chainlink/relayer_chain_interoperators.go index e17d4d516e9..3ed3c3242ba 100644 --- a/core/services/chainlink/relayer_chain_interoperators.go +++ b/core/services/chainlink/relayer_chain_interoperators.go @@ -8,6 +8,7 @@ import ( "sync" "github.com/smartcontractkit/chainlink-common/pkg/loop" + relay "github.com/smartcontractkit/chainlink-common/pkg/loop/adapters/relay" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos" "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/adapters" @@ -16,7 +17,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/services" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2" - "github.com/smartcontractkit/chainlink/v2/core/services/relay" ) var ErrNoSuchRelayer = errors.New("relayer does not exist") @@ -183,6 +183,17 @@ func (rs *CoreRelayerChainInteroperators) Get(id types.RelayID) (loop.Relayer, e return lr, nil } +func (rs *CoreRelayerChainInteroperators) GetIDToRelayerMap() (map[types.RelayID]loop.Relayer, error) { + rs.mu.Lock() + defer rs.mu.Unlock() + result := make(map[types.RelayID]loop.Relayer) + for id, relayer := range rs.loopRelayers { + result[id] = relayer + } + + return result, nil +} + // LegacyEVMChains returns a container with all the evm chains // TODO BCF-2511 func (rs *CoreRelayerChainInteroperators) LegacyEVMChains() legacyevm.LegacyChainContainer { diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go index 31645b7c54d..8bb06538f03 100644 --- a/core/services/chainlink/relayer_factory.go +++ b/core/services/chainlink/relayer_factory.go @@ -8,6 +8,7 @@ import ( "github.com/pelletier/go-toml/v2" "github.com/smartcontractkit/chainlink-common/pkg/loop" + "github.com/smartcontractkit/chainlink-common/pkg/loop/adapters/relay" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos" @@ -23,7 +24,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/config/env" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - "github.com/smartcontractkit/chainlink/v2/core/services/relay" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc" "github.com/smartcontractkit/chainlink/v2/plugins" diff --git a/core/services/job/spawner_test.go b/core/services/job/spawner_test.go index 7b4ab138e7c..ef55021dabf 100644 --- a/core/services/job/spawner_test.go +++ b/core/services/job/spawner_test.go @@ -73,6 +73,10 @@ func (g *relayGetter) Get(id types.RelayID) (loop.Relayer, error) { return evmrelayer.NewLoopRelayServerAdapter(g.r, g.e), nil } +func (g *relayGetter) GetIDToRelayerMap() (map[types.RelayID]loop.Relayer, error) { + return map[types.RelayID]loop.Relayer{}, nil +} + func TestSpawner_CreateJobDeleteJob(t *testing.T) { t.Parallel() ctx := testutils.Context(t) diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go index 4e1eb0cc623..7747cad3360 100644 --- a/core/services/ocr2/delegate.go +++ b/core/services/ocr2/delegate.go @@ -25,26 +25,22 @@ import ( ocr2keepers20runner "github.com/smartcontractkit/chainlink-automation/pkg/v2/runner" ocr2keepers21config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config" ocr2keepers21 "github.com/smartcontractkit/chainlink-automation/pkg/v3/plugin" - "github.com/smartcontractkit/chainlink-common/pkg/loop/reportingplugins/ocr3" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - - "github.com/smartcontractkit/chainlink/v2/core/config/env" - - "github.com/smartcontractkit/chainlink-vrf/altbn_128" - dkgpkg "github.com/smartcontractkit/chainlink-vrf/dkg" - "github.com/smartcontractkit/chainlink-vrf/ocr2vrf" - commonlogger "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/loop" "github.com/smartcontractkit/chainlink-common/pkg/loop/reportingplugins" + "github.com/smartcontractkit/chainlink-common/pkg/loop/reportingplugins/ocr3" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/types/core" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" - + "github.com/smartcontractkit/chainlink-vrf/altbn_128" + dkgpkg "github.com/smartcontractkit/chainlink-vrf/dkg" + "github.com/smartcontractkit/chainlink-vrf/ocr2vrf" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" coreconfig "github.com/smartcontractkit/chainlink/v2/core/config" + "github.com/smartcontractkit/chainlink/v2/core/config/env" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" @@ -71,7 +67,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - "github.com/smartcontractkit/chainlink/v2/core/services/relay" evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" functionsRelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/functions" evmmercury "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury" @@ -108,6 +103,7 @@ func (e ErrRelayNotEnabled) Error() string { type RelayGetter interface { Get(id types.RelayID) (loop.Relayer, error) + GetIDToRelayerMap() (map[types.RelayID]loop.Relayer, error) } type Delegate struct { ds sqlutil.DataSource @@ -567,6 +563,11 @@ func (d *Delegate) newServicesGenericPlugin( return nil, ErrJobSpecNoRelayer{PluginName: pCfg.PluginName, Err: err} } + relayerSet, err := generic.NewRelayerSet(d.RelayGetter, jb.ExternalJobID, jb.ID, d.isNewlyCreatedJob) + if err != nil { + return nil, fmt.Errorf("failed to create relayer set: %w", err) + } + relayer, err := d.RelayGetter.Get(rid) if err != nil { return nil, ErrRelayNotEnabled{Err: err, Relay: spec.Relay, PluginName: pCfg.PluginName} @@ -620,7 +621,7 @@ func (d *Delegate) newServicesGenericPlugin( //TODO: remove this workaround when the EVM relayer is running inside of an LOOPP d.lggr.Info("provider is not a LOOPP provider, switching to provider server") - ps, err2 := relay.NewProviderServer(provider, types.OCR2PluginType(pCfg.ProviderType), d.lggr) + ps, err2 := loop.NewProviderServer(provider, types.OCR2PluginType(pCfg.ProviderType), d.lggr) if err2 != nil { return nil, fmt.Errorf("cannot start EVM provider server: %s", err2) } @@ -657,7 +658,7 @@ func (d *Delegate) newServicesGenericPlugin( switch pCfg.OCRVersion { case 2: plugin := reportingplugins.NewLOOPPService(pluginLggr, grpcOpts, cmdFn, pluginConfig, providerClientConn, pr, ta, - errorLog, keyValueStore) + errorLog, keyValueStore, relayerSet) oracleArgs := libocr2.OCR2OracleArgs{ BinaryNetworkEndpointFactory: d.peerWrapper.Peer2, V2Bootstrappers: bootstrapPeers, @@ -683,7 +684,7 @@ func (d *Delegate) newServicesGenericPlugin( case 3: //OCR3 with OCR2 OnchainKeyring and ContractTransmitter plugin := ocr3.NewLOOPPService(pluginLggr, grpcOpts, cmdFn, pluginConfig, providerClientConn, pr, ta, errorLog, - capabilitiesRegistry, keyValueStore) + capabilitiesRegistry, keyValueStore, relayerSet) contractTransmitter := ocrcommon.NewOCR3ContractTransmitterAdapter(provider.ContractTransmitter()) oracleArgs := libocr2.OCR3OracleArgs[[]byte]{ BinaryNetworkEndpointFactory: d.peerWrapper.Peer2, diff --git a/core/services/ocr2/plugins/generic/relayerset.go b/core/services/ocr2/plugins/generic/relayerset.go new file mode 100644 index 00000000000..0586f600c50 --- /dev/null +++ b/core/services/ocr2/plugins/generic/relayerset.go @@ -0,0 +1,87 @@ +package generic + +import ( + "context" + "fmt" + + "github.com/google/uuid" + + "github.com/smartcontractkit/chainlink-common/pkg/loop" + "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/types/core" +) + +type RelayGetter interface { + GetIDToRelayerMap() (map[types.RelayID]loop.Relayer, error) +} + +type RelayerSet struct { + wrappedRelayers map[types.RelayID]core.Relayer +} + +func NewRelayerSet(relayGetter RelayGetter, externalJobID uuid.UUID, jobID int32, isNew bool) (*RelayerSet, error) { + + wrappedRelayers := map[types.RelayID]core.Relayer{} + + relayers, err := relayGetter.GetIDToRelayerMap() + if err != nil { + return nil, fmt.Errorf("failed to get relayers: %w", err) + } + + for id, relayer := range relayers { + wrappedRelayers[id] = relayerWrapper{Relayer: relayer, ExternalJobID: externalJobID, JobID: jobID, New: isNew} + } + + return &RelayerSet{wrappedRelayers: wrappedRelayers}, nil +} + +func (r *RelayerSet) Get(_ context.Context, id types.RelayID) (core.Relayer, error) { + if relayer, ok := r.wrappedRelayers[id]; ok { + return relayer, nil + } + + return nil, fmt.Errorf("relayer with id %s not found", id) +} + +func (r *RelayerSet) List(_ context.Context, relayIDs ...types.RelayID) (map[types.RelayID]core.Relayer, error) { + + if len(relayIDs) == 0 { + return r.wrappedRelayers, nil + } + + filterer := map[types.RelayID]bool{} + for _, id := range relayIDs { + filterer[id] = true + } + + result := map[types.RelayID]core.Relayer{} + for id, relayer := range r.wrappedRelayers { + if _, ok := filterer[id]; ok { + result[id] = relayer + } + } + + return result, nil +} + +type relayerWrapper struct { + loop.Relayer + ExternalJobID uuid.UUID + JobID int32 + New bool // Whether this is a first time job add. +} + +func (r relayerWrapper) NewPluginProvider(ctx context.Context, rargs core.RelayArgs, pargs core.PluginArgs) (types.PluginProvider, error) { + + relayArgs := types.RelayArgs{ + ExternalJobID: r.ExternalJobID, + JobID: r.JobID, + ContractID: rargs.ContractID, + New: r.New, + RelayConfig: rargs.RelayConfig, + ProviderType: rargs.ProviderType, + MercuryCredentials: rargs.MercuryCredentials, + } + + return r.Relayer.NewPluginProvider(ctx, relayArgs, types.PluginArgs(pargs)) +} diff --git a/core/services/ocr2/plugins/generic/relayerset_test.go b/core/services/ocr2/plugins/generic/relayerset_test.go new file mode 100644 index 00000000000..9aef7e29d78 --- /dev/null +++ b/core/services/ocr2/plugins/generic/relayerset_test.go @@ -0,0 +1,173 @@ +package generic + +import ( + "context" + "fmt" + "math/big" + "testing" + + "github.com/google/uuid" + "github.com/stretchr/testify/assert" + + "github.com/smartcontractkit/chainlink-common/pkg/loop" + "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/types/core" +) + +func TestRelayerSet_List(t *testing.T) { + + testRelayersMap := map[types.RelayID]loop.Relayer{} + testRelayersMap[types.RelayID{Network: "N1", ChainID: "C1"}] = &TestRelayer{} + testRelayersMap[types.RelayID{Network: "N2", ChainID: "C2"}] = &TestRelayer{} + testRelayersMap[types.RelayID{Network: "N3", ChainID: "C3"}] = &TestRelayer{} + + testGetter := TestRelayGetter{relayers: testRelayersMap} + + relayerSet, err := NewRelayerSet(testGetter, uuid.New(), 1, true) + assert.NoError(t, err) + relayers, err := relayerSet.List(context.Background()) + assert.NoError(t, err) + + assert.Equal(t, len(relayers), 3) + + relayers, err = relayerSet.List(context.Background(), types.RelayID{Network: "N1", ChainID: "C1"}, types.RelayID{Network: "N3", ChainID: "C3"}) + assert.NoError(t, err) + + assert.Equal(t, len(relayers), 2) + + _, ok := relayers[types.RelayID{Network: "N1", ChainID: "C1"}] + assert.True(t, ok) + + _, ok = relayers[types.RelayID{Network: "N3", ChainID: "C3"}] + assert.True(t, ok) +} + +func TestRelayerSet_Get(t *testing.T) { + + testRelayersMap := map[types.RelayID]loop.Relayer{} + testRelayersMap[types.RelayID{Network: "N1", ChainID: "C1"}] = &TestRelayer{} + testRelayersMap[types.RelayID{Network: "N2", ChainID: "C2"}] = &TestRelayer{} + testRelayersMap[types.RelayID{Network: "N3", ChainID: "C3"}] = &TestRelayer{} + + testGetter := TestRelayGetter{relayers: testRelayersMap} + + relayerSet, err := NewRelayerSet(testGetter, uuid.New(), 1, true) + assert.NoError(t, err) + + _, err = relayerSet.Get(context.Background(), types.RelayID{Network: "N1", ChainID: "C1"}) + assert.NoError(t, err) + + _, err = relayerSet.Get(context.Background(), types.RelayID{Network: "N4", ChainID: "C4"}) + assert.NotNil(t, err) +} + +func TestRelayerSet_NewPluginProvider(t *testing.T) { + testRelayersMap := map[types.RelayID]loop.Relayer{} + testRelayer := &TestRelayer{} + testRelayersMap[types.RelayID{Network: "N1", ChainID: "C1"}] = testRelayer + testRelayersMap[types.RelayID{Network: "N2", ChainID: "C2"}] = &TestRelayer{} + testRelayersMap[types.RelayID{Network: "N3", ChainID: "C3"}] = &TestRelayer{} + + testGetter := TestRelayGetter{relayers: testRelayersMap} + + externalJobID := uuid.New() + relayerSet, err := NewRelayerSet(testGetter, externalJobID, 1, true) + assert.NoError(t, err) + + relayer, err := relayerSet.Get(context.Background(), types.RelayID{Network: "N1", ChainID: "C1"}) + assert.NoError(t, err) + + _, err = relayer.NewPluginProvider(context.Background(), core.RelayArgs{ + ContractID: "c1", + RelayConfig: []byte("relayconfig"), + ProviderType: "p1", + MercuryCredentials: &types.MercuryCredentials{ + LegacyURL: "legacy", + URL: "url", + Username: "user", + Password: "pass", + }, + }, core.PluginArgs{ + TransmitterID: "t1", + PluginConfig: []byte("pluginconfig"), + }) + assert.NoError(t, err) + + assert.Equal(t, types.RelayArgs{ + ExternalJobID: externalJobID, + JobID: 1, + ContractID: "c1", + New: true, + RelayConfig: []byte("relayconfig"), + ProviderType: "p1", + MercuryCredentials: &types.MercuryCredentials{ + LegacyURL: "legacy", + URL: "url", + Username: "user", + Password: "pass", + }, + }, testRelayer.relayArgs) + + assert.Equal(t, types.PluginArgs{ + TransmitterID: "t1", + PluginConfig: []byte("pluginconfig"), + }, testRelayer.pluginArgs) +} + +type TestRelayGetter struct { + relayers map[types.RelayID]loop.Relayer +} + +func (t TestRelayGetter) Get(id types.RelayID) (loop.Relayer, error) { + if relayer, ok := t.relayers[id]; ok { + return relayer, nil + } + + return nil, fmt.Errorf("relayer with id %s not found", id) +} + +func (t TestRelayGetter) GetIDToRelayerMap() (map[types.RelayID]loop.Relayer, error) { + return t.relayers, nil +} + +type TestRelayer struct { + relayArgs types.RelayArgs + pluginArgs types.PluginArgs +} + +func (t *TestRelayer) NewPluginProvider(ctx context.Context, args types.RelayArgs, args2 types.PluginArgs) (types.PluginProvider, error) { + t.relayArgs = args + t.pluginArgs = args2 + + return nil, nil +} + +func (t *TestRelayer) Name() string { panic("implement me") } + +func (t *TestRelayer) Start(ctx context.Context) error { panic("implement me") } + +func (t *TestRelayer) Close() error { panic("implement me") } + +func (t *TestRelayer) Ready() error { panic("implement me") } + +func (t *TestRelayer) HealthReport() map[string]error { panic("implement me") } + +func (t *TestRelayer) GetChainStatus(ctx context.Context) (types.ChainStatus, error) { + panic("implement me") +} + +func (t *TestRelayer) ListNodeStatuses(ctx context.Context, pageSize int32, pageToken string) (stats []types.NodeStatus, nextPageToken string, total int, err error) { + panic("implement me") +} + +func (t *TestRelayer) Transact(ctx context.Context, from, to string, amount *big.Int, balanceCheck bool) error { + panic("implement me") +} + +func (t *TestRelayer) NewConfigProvider(ctx context.Context, args types.RelayArgs) (types.ConfigProvider, error) { + panic("implement me") +} + +func (t *TestRelayer) NewLLOProvider(ctx context.Context, args types.RelayArgs, args2 types.PluginArgs) (types.LLOProvider, error) { + panic("implement me") +} diff --git a/core/services/ocrbootstrap/delegate.go b/core/services/ocrbootstrap/delegate.go index 0bb7a0ca2ba..4f927faa009 100644 --- a/core/services/ocrbootstrap/delegate.go +++ b/core/services/ocrbootstrap/delegate.go @@ -22,6 +22,7 @@ import ( type RelayGetter interface { Get(types.RelayID) (loop.Relayer, error) + GetIDToRelayerMap() (map[types.RelayID]loop.Relayer, error) } // Delegate creates Bootstrap jobs diff --git a/core/services/relay/evm/loop_impl.go b/core/services/relay/evm/loop_impl.go index 57a09dd49ae..7f9d405847d 100644 --- a/core/services/relay/evm/loop_impl.go +++ b/core/services/relay/evm/loop_impl.go @@ -2,9 +2,9 @@ package evm import ( "github.com/smartcontractkit/chainlink-common/pkg/loop" + relay "github.com/smartcontractkit/chainlink-common/pkg/loop/adapters/relay" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" - "github.com/smartcontractkit/chainlink/v2/core/services/relay" ) //go:generate mockery --quiet --name LoopRelayAdapter --output ./mocks/ --case=underscore diff --git a/core/services/relay/evm/relayer_extender.go b/core/services/relay/evm/relayer_extender.go index 83f03b47f9e..5f49a0b16c9 100644 --- a/core/services/relay/evm/relayer_extender.go +++ b/core/services/relay/evm/relayer_extender.go @@ -8,7 +8,7 @@ import ( "github.com/pkg/errors" "go.uber.org/multierr" - "github.com/smartcontractkit/chainlink-common/pkg/loop" + "github.com/smartcontractkit/chainlink-common/pkg/loop/adapters/relay" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" @@ -19,7 +19,7 @@ import ( var ErrNoChains = errors.New("no EVM chains loaded") type EVMChainRelayerExtender interface { - loop.RelayerExt + relay.RelayerExt Chain() legacyevm.Chain } diff --git a/core/services/relay/grpc_provider_server.go b/core/services/relay/grpc_provider_server.go deleted file mode 100644 index 67bbb8c6c2a..00000000000 --- a/core/services/relay/grpc_provider_server.go +++ /dev/null @@ -1,68 +0,0 @@ -package relay - -import ( - "context" - "net" - - "go.uber.org/multierr" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" - - "github.com/smartcontractkit/chainlink-common/pkg/loop" - "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -type ProviderServer struct { - s *grpc.Server - lis net.Listener - lggr logger.Logger - conns []*grpc.ClientConn -} - -func (p *ProviderServer) Start(ctx context.Context) error { - p.serve() - return nil -} - -func (p *ProviderServer) Close() error { - var err error - for _, c := range p.conns { - err = multierr.Combine(err, c.Close()) - } - p.s.Stop() - return err -} - -func (p *ProviderServer) GetConn() (*grpc.ClientConn, error) { - cc, err := grpc.Dial(p.lis.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials())) - p.conns = append(p.conns, cc) - return cc, err -} - -// NewProviderServer creates a GRPC server that will wrap a provider, this is a workaround to test the Node API PoC until the EVM relayer is loopifyed -func NewProviderServer(p types.PluginProvider, pType types.OCR2PluginType, lggr logger.Logger) (*ProviderServer, error) { - lis, err := net.Listen("tcp", "127.0.0.1:0") - if err != nil { - return nil, err - } - ps := ProviderServer{ - s: grpc.NewServer(), - lis: lis, - lggr: lggr.Named("EVM.ProviderServer"), - } - err = loop.RegisterStandAloneProvider(ps.s, p, pType) - if err != nil { - return nil, err - } - - return &ps, nil -} - -func (p *ProviderServer) serve() { - go func() { - if err := p.s.Serve(p.lis); err != nil { - p.lggr.Errorf("Failed to serve EVM provider server: %v", err) - } - }() -} diff --git a/core/services/relay/grpc_provider_server_test.go b/core/services/relay/grpc_provider_server_test.go deleted file mode 100644 index 72bbbca0f44..00000000000 --- a/core/services/relay/grpc_provider_server_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package relay - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/types" - - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -func TestProviderServer(t *testing.T) { - r := &mockRelayer{} - sa := NewServerAdapter(r, mockRelayerExt{}) - mp, _ := sa.NewPluginProvider(testutils.Context(t), types.RelayArgs{ProviderType: string(types.Median)}, types.PluginArgs{}) - - lggr := logger.TestLogger(t) - _, err := NewProviderServer(mp, "unsupported-type", lggr) - require.ErrorContains(t, err, "unsupported-type") - - ps, err := NewProviderServer(staticMedianProvider{}, types.Median, lggr) - require.NoError(t, err) - - _, err = ps.GetConn() - require.NoError(t, err) -} diff --git a/core/services/relay/relay.go b/core/services/relay/relay.go deleted file mode 100644 index b4cc4517390..00000000000 --- a/core/services/relay/relay.go +++ /dev/null @@ -1,38 +0,0 @@ -package relay - -import ( - "context" - "fmt" - - "github.com/smartcontractkit/chainlink-common/pkg/loop" - "github.com/smartcontractkit/chainlink-common/pkg/types" -) - -// ServerAdapter extends [loop.RelayerAdapter] by overriding NewPluginProvider to dispatches calls according to `RelayArgs.ProviderType`. -// This should only be used to adapt relayers not running via GRPC in a LOOPP. -type ServerAdapter struct { - loop.RelayerAdapter -} - -// NewServerAdapter returns a new ServerAdapter. -func NewServerAdapter(r types.Relayer, e loop.RelayerExt) *ServerAdapter { //nolint:staticcheck - return &ServerAdapter{RelayerAdapter: loop.RelayerAdapter{Relayer: r, RelayerExt: e}} -} - -func (r *ServerAdapter) NewPluginProvider(ctx context.Context, rargs types.RelayArgs, pargs types.PluginArgs) (types.PluginProvider, error) { - switch types.OCR2PluginType(rargs.ProviderType) { - case types.Median: - return r.NewMedianProvider(ctx, rargs, pargs) - case types.Functions: - return r.NewFunctionsProvider(ctx, rargs, pargs) - case types.Mercury: - return r.NewMercuryProvider(ctx, rargs, pargs) - case types.OCR2Keeper: - return r.NewAutomationProvider(ctx, rargs, pargs) - case types.DKG, types.OCR2VRF, types.GenericPlugin: - return r.RelayerAdapter.NewPluginProvider(ctx, rargs, pargs) - case types.LLO, types.CCIPCommit, types.CCIPExecution: - return nil, fmt.Errorf("provider type not supported: %s", rargs.ProviderType) - } - return nil, fmt.Errorf("provider type not recognized: %s", rargs.ProviderType) -} diff --git a/core/services/relay/relay_test.go b/core/services/relay/relay_test.go deleted file mode 100644 index c0b2248ed1a..00000000000 --- a/core/services/relay/relay_test.go +++ /dev/null @@ -1,191 +0,0 @@ -package relay - -import ( - "context" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/smartcontractkit/libocr/offchainreporting2/reportingplugin/median" - ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - - "github.com/smartcontractkit/chainlink-common/pkg/loop" - "github.com/smartcontractkit/chainlink-common/pkg/types" - - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" -) - -type staticMedianProvider struct { -} - -var _ types.MedianProvider = staticMedianProvider{} - -// ContractConfigTracker implements types.MedianProvider. -func (s staticMedianProvider) ContractConfigTracker() ocr2types.ContractConfigTracker { - return nil -} - -// ContractTransmitter implements types.MedianProvider. -func (s staticMedianProvider) ContractTransmitter() ocr2types.ContractTransmitter { - return nil -} - -// MedianContract implements types.MedianProvider. -func (s staticMedianProvider) MedianContract() median.MedianContract { - return nil -} - -// OffchainConfigDigester implements types.MedianProvider. -func (s staticMedianProvider) OffchainConfigDigester() ocr2types.OffchainConfigDigester { - return nil -} - -// OnchainConfigCodec implements types.MedianProvider. -func (s staticMedianProvider) OnchainConfigCodec() median.OnchainConfigCodec { - return nil -} - -// ReportCodec implements types.MedianProvider. -func (s staticMedianProvider) ReportCodec() median.ReportCodec { - return nil -} - -// ChainReader implements types.MedianProvider. -func (s staticMedianProvider) ChainReader() types.ChainReader { - return nil -} - -// Close implements types.MedianProvider. -func (s staticMedianProvider) Close() error { - return nil -} - -// Codec implements types.MedianProvider. -func (s staticMedianProvider) Codec() types.Codec { - return nil -} - -// HealthReport implements types.MedianProvider. -func (s staticMedianProvider) HealthReport() map[string]error { - return nil -} - -// Name implements types.MedianProvider. -func (s staticMedianProvider) Name() string { - return "" -} - -// Ready implements types.MedianProvider. -func (s staticMedianProvider) Ready() error { - return nil -} - -// Start implements types.MedianProvider. -func (s staticMedianProvider) Start(context.Context) error { - return nil -} - -type staticFunctionsProvider struct { - types.FunctionsProvider -} - -type staticMercuryProvider struct { - types.MercuryProvider -} - -type staticAutomationProvider struct { - types.AutomationProvider -} - -type staticPluginProvider struct { - types.PluginProvider -} - -type mockRelayer struct { - types.Relayer -} - -func (m *mockRelayer) NewMedianProvider(rargs types.RelayArgs, pargs types.PluginArgs) (types.MedianProvider, error) { - return staticMedianProvider{}, nil -} - -func (m *mockRelayer) NewFunctionsProvider(rargs types.RelayArgs, pargs types.PluginArgs) (types.FunctionsProvider, error) { - return staticFunctionsProvider{}, nil -} - -func (m *mockRelayer) NewMercuryProvider(rargs types.RelayArgs, pargs types.PluginArgs) (types.MercuryProvider, error) { - return staticMercuryProvider{}, nil -} - -func (m *mockRelayer) NewAutomationProvider(rargs types.RelayArgs, pargs types.PluginArgs) (types.AutomationProvider, error) { - return staticAutomationProvider{}, nil -} - -func (m *mockRelayer) NewPluginProvider(rargs types.RelayArgs, pargs types.PluginArgs) (types.PluginProvider, error) { - return staticPluginProvider{}, nil -} - -type mockRelayerExt struct { - loop.RelayerExt -} - -func isType[T any](p any) bool { - _, ok := p.(T) - return ok -} - -func TestRelayerServerAdapter(t *testing.T) { - r := &mockRelayer{} - sa := NewServerAdapter(r, mockRelayerExt{}) - - testCases := []struct { - ProviderType string - Test func(p any) bool - Error string - }{ - { - ProviderType: string(types.Median), - Test: isType[types.MedianProvider], - }, - { - ProviderType: string(types.Functions), - Test: isType[types.FunctionsProvider], - }, - { - ProviderType: string(types.Mercury), - Test: isType[types.MercuryProvider], - }, - { - ProviderType: string(types.CCIPCommit), - Error: "provider type not supported", - }, - { - ProviderType: string(types.CCIPExecution), - Error: "provider type not supported", - }, - { - ProviderType: "unknown", - Error: "provider type not recognized", - }, - { - ProviderType: string(types.GenericPlugin), - Test: isType[types.PluginProvider], - }, - } - - ctx := testutils.Context(t) - for _, tc := range testCases { - pp, err := sa.NewPluginProvider( - ctx, - types.RelayArgs{ProviderType: tc.ProviderType}, - types.PluginArgs{}, - ) - - if tc.Error != "" { - assert.ErrorContains(t, err, tc.Error) - } else { - assert.NoError(t, err) - assert.True(t, tc.Test(pp)) - } - } -} diff --git a/go.mod b/go.mod index 6e081467bc0..923e4b87b0d 100644 --- a/go.mod +++ b/go.mod @@ -72,7 +72,7 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chain-selectors v1.0.10 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 github.com/smartcontractkit/chainlink-feeds v0.0.0-20240422130241-13c17a91b2ab diff --git a/go.sum b/go.sum index 50cb9f3b44f..90faeacb057 100644 --- a/go.sum +++ b/go.sum @@ -1180,8 +1180,8 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 h1:54hM3/SrOM166it2K35hGb5K7gQ49/Op0aHp9WkqpqU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb h1:nJ9dkgvX5vdpFWhYufnRUAiNvNHsXkoBL6C0bDerq/k= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee h1:eFuBKyEbL2b+eyfgV/Eu9+8HuCEev+IcBi+K9l1dG7g= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 69c09244ef8..0903711f16e 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -25,7 +25,7 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb github.com/smartcontractkit/chainlink-testing-framework v1.28.4 github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index e2be6f36438..d9bb628d861 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1517,8 +1517,8 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 h1:54hM3/SrOM166it2K35hGb5K7gQ49/Op0aHp9WkqpqU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb h1:nJ9dkgvX5vdpFWhYufnRUAiNvNHsXkoBL6C0bDerq/k= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee h1:eFuBKyEbL2b+eyfgV/Eu9+8HuCEev+IcBi+K9l1dG7g= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 128c611c04d..a4c5b67c204 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -16,7 +16,7 @@ require ( github.com/rs/zerolog v1.30.0 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb github.com/smartcontractkit/chainlink-testing-framework v1.28.4 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 291f221f4b8..e2d5b5270ff 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1500,8 +1500,8 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73 h1:54hM3/SrOM166it2K35hGb5K7gQ49/Op0aHp9WkqpqU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240424132620-add4946c1c73/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb h1:nJ9dkgvX5vdpFWhYufnRUAiNvNHsXkoBL6C0bDerq/k= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee h1:eFuBKyEbL2b+eyfgV/Eu9+8HuCEev+IcBi+K9l1dG7g= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419213354-ea34a948e2ee/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/plugins/medianpoc/plugin.go b/plugins/medianpoc/plugin.go index b937361b9ec..bbd9d437e3a 100644 --- a/plugins/medianpoc/plugin.go +++ b/plugins/medianpoc/plugin.go @@ -66,6 +66,7 @@ func (p *Plugin) NewReportingPluginFactory( telemetry core.TelemetryClient, errorLog core.ErrorLog, keyValueStore core.KeyValueStore, + relayerSet core.RelayerSet, ) (types.ReportingPluginFactory, error) { f, err := p.newFactory(ctx, config, provider, pipelineRunner, telemetry, errorLog) if err != nil { From 208801569f215c904d8c051a3f677b51be60c7b5 Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Mon, 29 Apr 2024 18:58:00 +0200 Subject: [PATCH 06/45] [TT-970] Migrate Atlas-specific contracts to Seth (#13027) * use latest Seth * WIP#1 * migrate Atlas-specific contracts to Seth * use latest CTF * remove trash * fix mock deployment * use latest CTF * update CTF again * update CTF * use CTF release version --- go.mod | 1 - .../contracts/contract_deployer.go | 10 +- .../contracts/etherem_contracts_atlas_seth.go | 392 ++++++++++++++++++ .../contracts/ethereum_contracts.go | 106 ++--- integration-tests/go.mod | 4 +- integration-tests/go.sum | 8 +- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 +- 8 files changed, 459 insertions(+), 68 deletions(-) create mode 100644 integration-tests/contracts/etherem_contracts_atlas_seth.go diff --git a/go.mod b/go.mod index 923e4b87b0d..3e691e95405 100644 --- a/go.mod +++ b/go.mod @@ -353,5 +353,4 @@ replace ( // until merged upstream: https://github.com/mwitkow/grpc-proxy/pull/69 github.com/mwitkow/grpc-proxy => github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f - ) diff --git a/integration-tests/contracts/contract_deployer.go b/integration-tests/contracts/contract_deployer.go index c85c927b8d4..e2511c7292e 100644 --- a/integration-tests/contracts/contract_deployer.go +++ b/integration-tests/contracts/contract_deployer.go @@ -435,7 +435,7 @@ func (e *EthereumContractDeployer) DeployStakingEventsMock() (StakingEventsMock, if err != nil { return nil, err } - return &EthereumStakingEventsMock{ + return &LegacyEthereumStakingEventsMock{ client: e.client, eventsMock: instance.(*eth_contracts.StakingEventsMock), address: address, @@ -452,7 +452,7 @@ func (e *EthereumContractDeployer) DeployFunctionsV1EventsMock() (FunctionsV1Eve if err != nil { return nil, err } - return &EthereumFunctionsV1EventsMock{ + return &LegacyEthereumFunctionsV1EventsMock{ client: e.client, eventsMock: instance.(*functions_v1_events_mock.FunctionsV1EventsMock), address: address, @@ -469,7 +469,7 @@ func (e *EthereumContractDeployer) DeployKeeperRegistry11Mock() (KeeperRegistry1 if err != nil { return nil, err } - return &EthereumKeeperRegistry11Mock{ + return &LegacyEthereumKeeperRegistry11Mock{ client: e.client, registryMock: instance.(*keeper_registry_wrapper1_1_mock.KeeperRegistryMock), address: address, @@ -486,7 +486,7 @@ func (e *EthereumContractDeployer) DeployKeeperRegistrar12Mock() (KeeperRegistra if err != nil { return nil, err } - return &EthereumKeeperRegistrar12Mock{ + return &LegacyEthereumKeeperRegistrar12Mock{ client: e.client, registrarMock: instance.(*keeper_registrar_wrapper1_2_mock.KeeperRegistrarMock), address: address, @@ -503,7 +503,7 @@ func (e *EthereumContractDeployer) DeployKeeperGasWrapperMock() (KeeperGasWrappe if err != nil { return nil, err } - return &EthereumKeeperGasWrapperMock{ + return &LegacyEthereumKeeperGasWrapperMock{ client: e.client, gasWrapperMock: instance.(*gas_wrapper_mock.KeeperRegistryCheckUpkeepGasUsageWrapperMock), address: address, diff --git a/integration-tests/contracts/etherem_contracts_atlas_seth.go b/integration-tests/contracts/etherem_contracts_atlas_seth.go new file mode 100644 index 00000000000..c28e5198682 --- /dev/null +++ b/integration-tests/contracts/etherem_contracts_atlas_seth.go @@ -0,0 +1,392 @@ +package contracts + +import ( + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/seth" + + eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" + "github.com/smartcontractkit/chainlink/integration-tests/wrappers" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/functions/generated/functions_v1_events_mock" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/gas_wrapper_mock" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registrar_wrapper1_2_mock" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/keeper_registry_wrapper1_1_mock" +) + +// EthereumFunctionsV1EventsMock represents the basic functions v1 events mock contract +type EthereumFunctionsV1EventsMock struct { + client *seth.Client + eventsMock *functions_v1_events_mock.FunctionsV1EventsMock + address *common.Address +} + +func (f *EthereumFunctionsV1EventsMock) Address() string { + return f.address.Hex() +} + +func (f *EthereumFunctionsV1EventsMock) EmitRequestProcessed(requestId [32]byte, subscriptionId uint64, totalCostJuels *big.Int, transmitter common.Address, resultCode uint8, response []byte, errByte []byte, callbackReturnData []byte) error { + _, err := f.client.Decode(f.eventsMock.EmitRequestProcessed(f.client.NewTXOpts(), requestId, subscriptionId, totalCostJuels, transmitter, resultCode, response, errByte, callbackReturnData)) + return err +} + +func (f *EthereumFunctionsV1EventsMock) EmitRequestStart(requestId [32]byte, donId [32]byte, subscriptionId uint64, subscriptionOwner common.Address, requestingContract common.Address, requestInitiator common.Address, data []byte, dataVersion uint16, callbackGasLimit uint32, estimatedTotalCostJuels *big.Int) error { + _, err := f.client.Decode(f.eventsMock.EmitRequestStart(f.client.NewTXOpts(), requestId, donId, subscriptionId, subscriptionOwner, requestingContract, requestInitiator, data, dataVersion, callbackGasLimit, estimatedTotalCostJuels)) + return err +} + +func (f *EthereumFunctionsV1EventsMock) EmitSubscriptionCanceled(subscriptionId uint64, fundsRecipient common.Address, fundsAmount *big.Int) error { + _, err := f.client.Decode(f.eventsMock.EmitSubscriptionCanceled(f.client.NewTXOpts(), subscriptionId, fundsRecipient, fundsAmount)) + return err +} + +func (f *EthereumFunctionsV1EventsMock) EmitSubscriptionConsumerAdded(subscriptionId uint64, consumer common.Address) error { + _, err := f.client.Decode(f.eventsMock.EmitSubscriptionConsumerAdded(f.client.NewTXOpts(), subscriptionId, consumer)) + return err +} + +func (f *EthereumFunctionsV1EventsMock) EmitSubscriptionConsumerRemoved(subscriptionId uint64, consumer common.Address) error { + _, err := f.client.Decode(f.eventsMock.EmitSubscriptionConsumerRemoved(f.client.NewTXOpts(), subscriptionId, consumer)) + return err +} + +func (f *EthereumFunctionsV1EventsMock) EmitSubscriptionCreated(subscriptionId uint64, owner common.Address) error { + _, err := f.client.Decode(f.eventsMock.EmitSubscriptionCreated(f.client.NewTXOpts(), subscriptionId, owner)) + return err +} + +func (f *EthereumFunctionsV1EventsMock) EmitSubscriptionFunded(subscriptionId uint64, oldBalance *big.Int, newBalance *big.Int) error { + _, err := f.client.Decode(f.eventsMock.EmitSubscriptionFunded(f.client.NewTXOpts(), subscriptionId, oldBalance, newBalance)) + return err +} + +func (f *EthereumFunctionsV1EventsMock) EmitSubscriptionOwnerTransferred(subscriptionId uint64, from common.Address, to common.Address) error { + _, err := f.client.Decode(f.eventsMock.EmitSubscriptionOwnerTransferred(f.client.NewTXOpts(), subscriptionId, from, to)) + return err +} + +func (f *EthereumFunctionsV1EventsMock) EmitSubscriptionOwnerTransferRequested(subscriptionId uint64, from common.Address, to common.Address) error { + _, err := f.client.Decode(f.eventsMock.EmitSubscriptionOwnerTransferRequested(f.client.NewTXOpts(), subscriptionId, from, to)) + return err +} + +func (f *EthereumFunctionsV1EventsMock) EmitRequestNotProcessed(requestId [32]byte, coordinator common.Address, transmitter common.Address, resultCode uint8) error { + _, err := f.client.Decode(f.eventsMock.EmitRequestNotProcessed(f.client.NewTXOpts(), requestId, coordinator, transmitter, resultCode)) + return err +} + +func (f *EthereumFunctionsV1EventsMock) EmitContractUpdated(id [32]byte, from common.Address, to common.Address) error { + _, err := f.client.Decode(f.eventsMock.EmitContractUpdated(f.client.NewTXOpts(), id, from, to)) + return err +} + +// DeployFunctionsV1EventsMock deploys a new instance of the FunctionsV1EventsMock contract +func DeployFunctionsV1EventsMock(client *seth.Client) (FunctionsV1EventsMock, error) { + abi, err := functions_v1_events_mock.FunctionsV1EventsMockMetaData.GetAbi() + if err != nil { + return &EthereumFunctionsV1EventsMock{}, fmt.Errorf("failed to get FunctionsV1EventsMock ABI: %w", err) + } + client.ContractStore.AddABI("FunctionsV1EventsMock", *abi) + client.ContractStore.AddBIN("FunctionsV1EventsMock", common.FromHex(functions_v1_events_mock.FunctionsV1EventsMockMetaData.Bin)) + + data, err := client.DeployContract(client.NewTXOpts(), "FunctionsV1EventsMock", *abi, common.FromHex(functions_v1_events_mock.FunctionsV1EventsMockMetaData.Bin)) + + if err != nil { + return &EthereumFunctionsV1EventsMock{}, fmt.Errorf("FunctionsV1EventsMock instance deployment have failed: %w", err) + } + + instance, err := functions_v1_events_mock.NewFunctionsV1EventsMock(data.Address, wrappers.MustNewWrappedContractBackend(nil, client)) + if err != nil { + return &EthereumFunctionsV1EventsMock{}, fmt.Errorf("failed to instantiate FunctionsV1EventsMock instance: %w", err) + } + + return &EthereumFunctionsV1EventsMock{ + client: client, + eventsMock: instance, + address: &data.Address, + }, nil +} + +// EthereumKeeperRegistry11Mock represents the basic keeper registry 1.1 mock contract +type EthereumKeeperRegistry11Mock struct { + client *seth.Client + registryMock *keeper_registry_wrapper1_1_mock.KeeperRegistryMock + address *common.Address +} + +func (f *EthereumKeeperRegistry11Mock) Address() string { + return f.address.Hex() +} + +func (f *EthereumKeeperRegistry11Mock) EmitUpkeepPerformed(id *big.Int, success bool, from common.Address, payment *big.Int, performData []byte) error { + _, err := f.client.Decode(f.registryMock.EmitUpkeepPerformed(f.client.NewTXOpts(), id, success, from, payment, performData)) + return err +} + +func (f *EthereumKeeperRegistry11Mock) EmitUpkeepCanceled(id *big.Int, atBlockHeight uint64) error { + _, err := f.client.Decode(f.registryMock.EmitUpkeepCanceled(f.client.NewTXOpts(), id, atBlockHeight)) + return err +} + +func (f *EthereumKeeperRegistry11Mock) EmitFundsWithdrawn(id *big.Int, amount *big.Int, to common.Address) error { + _, err := f.client.Decode(f.registryMock.EmitFundsWithdrawn(f.client.NewTXOpts(), id, amount, to)) + return err +} + +func (f *EthereumKeeperRegistry11Mock) EmitKeepersUpdated(keepers []common.Address, payees []common.Address) error { + _, err := f.client.Decode(f.registryMock.EmitKeepersUpdated(f.client.NewTXOpts(), keepers, payees)) + return err +} + +func (f *EthereumKeeperRegistry11Mock) EmitUpkeepRegistered(id *big.Int, executeGas uint32, admin common.Address) error { + _, err := f.client.Decode(f.registryMock.EmitUpkeepRegistered(f.client.NewTXOpts(), id, executeGas, admin)) + return err +} + +func (f *EthereumKeeperRegistry11Mock) EmitFundsAdded(id *big.Int, from common.Address, amount *big.Int) error { + _, err := f.client.Decode(f.registryMock.EmitFundsAdded(f.client.NewTXOpts(), id, from, amount)) + return err +} + +func (f *EthereumKeeperRegistry11Mock) SetUpkeepCount(upkeepCount *big.Int) error { + _, err := f.client.Decode(f.registryMock.SetUpkeepCount(f.client.NewTXOpts(), upkeepCount)) + return err +} + +func (f *EthereumKeeperRegistry11Mock) SetCanceledUpkeepList(canceledUpkeepList []*big.Int) error { + _, err := f.client.Decode(f.registryMock.SetCanceledUpkeepList(f.client.NewTXOpts(), canceledUpkeepList)) + return err +} + +func (f *EthereumKeeperRegistry11Mock) SetKeeperList(keepers []common.Address) error { + _, err := f.client.Decode(f.registryMock.SetKeeperList(f.client.NewTXOpts(), keepers)) + return err +} + +func (f *EthereumKeeperRegistry11Mock) SetConfig(paymentPremiumPPB uint32, flatFeeMicroLink uint32, blockCountPerTurn *big.Int, checkGasLimit uint32, stalenessSeconds *big.Int, gasCeilingMultiplier uint16, fallbackGasPrice *big.Int, fallbackLinkPrice *big.Int) error { + _, err := f.client.Decode(f.registryMock.SetConfig(f.client.NewTXOpts(), paymentPremiumPPB, flatFeeMicroLink, blockCountPerTurn, checkGasLimit, stalenessSeconds, gasCeilingMultiplier, fallbackGasPrice, fallbackLinkPrice)) + return err +} + +func (f *EthereumKeeperRegistry11Mock) SetUpkeep(id *big.Int, target common.Address, executeGas uint32, balance *big.Int, admin common.Address, maxValidBlocknumber uint64, lastKeeper common.Address, checkData []byte) error { + _, err := f.client.Decode(f.registryMock.SetUpkeep(f.client.NewTXOpts(), id, target, executeGas, balance, admin, maxValidBlocknumber, lastKeeper, checkData)) + return err +} + +func (f *EthereumKeeperRegistry11Mock) SetMinBalance(id *big.Int, minBalance *big.Int) error { + _, err := f.client.Decode(f.registryMock.SetMinBalance(f.client.NewTXOpts(), id, minBalance)) + return err +} + +func (f *EthereumKeeperRegistry11Mock) SetCheckUpkeepData(id *big.Int, performData []byte, maxLinkPayment *big.Int, gasLimit *big.Int, adjustedGasWei *big.Int, linkEth *big.Int) error { + _, err := f.client.Decode(f.registryMock.SetCheckUpkeepData(f.client.NewTXOpts(), id, performData, maxLinkPayment, gasLimit, adjustedGasWei, linkEth)) + return err +} + +func (f *EthereumKeeperRegistry11Mock) SetPerformUpkeepSuccess(id *big.Int, success bool) error { + _, err := f.client.Decode(f.registryMock.SetPerformUpkeepSuccess(f.client.NewTXOpts(), id, success)) + return err +} + +func DeployKeeperRegistry11Mock(client *seth.Client) (KeeperRegistry11Mock, error) { + abi, err := keeper_registry_wrapper1_1_mock.KeeperRegistryMockMetaData.GetAbi() + if err != nil { + return &EthereumKeeperRegistry11Mock{}, fmt.Errorf("failed to get KeeperRegistry11Mock ABI: %w", err) + } + client.ContractStore.AddABI("KeeperRegistry11Mock", *abi) + client.ContractStore.AddBIN("KeeperRegistry11Mock", common.FromHex(keeper_registry_wrapper1_1_mock.KeeperRegistryMockMetaData.Bin)) + + data, err := client.DeployContract(client.NewTXOpts(), "KeeperRegistry11Mock", *abi, common.FromHex(keeper_registry_wrapper1_1_mock.KeeperRegistryMockMetaData.Bin)) + + if err != nil { + return &EthereumKeeperRegistry11Mock{}, fmt.Errorf("KeeperRegistry11Mock instance deployment have failed: %w", err) + } + + instance, err := keeper_registry_wrapper1_1_mock.NewKeeperRegistryMock(data.Address, wrappers.MustNewWrappedContractBackend(nil, client)) + if err != nil { + return &EthereumKeeperRegistry11Mock{}, fmt.Errorf("failed to instantiate KeeperRegistry11Mock instance: %w", err) + } + + return &EthereumKeeperRegistry11Mock{ + client: client, + registryMock: instance, + address: &data.Address, + }, nil +} + +// EthereumKeeperRegistrar12Mock represents the basic keeper registrar 1.2 mock contract +type EthereumKeeperRegistrar12Mock struct { + client *seth.Client + registrarMock *keeper_registrar_wrapper1_2_mock.KeeperRegistrarMock + address *common.Address +} + +func (f *EthereumKeeperRegistrar12Mock) Address() string { + return f.address.Hex() +} + +func (f *EthereumKeeperRegistrar12Mock) EmitRegistrationRequested(hash [32]byte, name string, encryptedEmail []byte, upkeepContract common.Address, gasLimit uint32, adminAddress common.Address, checkData []byte, amount *big.Int, source uint8) error { + _, err := f.client.Decode(f.registrarMock.EmitRegistrationRequested(f.client.NewTXOpts(), hash, name, encryptedEmail, upkeepContract, gasLimit, adminAddress, checkData, amount, source)) + return err +} + +func (f *EthereumKeeperRegistrar12Mock) EmitRegistrationApproved(hash [32]byte, displayName string, upkeepId *big.Int) error { + _, err := f.client.Decode(f.registrarMock.EmitRegistrationApproved(f.client.NewTXOpts(), hash, displayName, upkeepId)) + return err +} + +func (f *EthereumKeeperRegistrar12Mock) SetRegistrationConfig(autoApproveConfigType uint8, autoApproveMaxAllowed uint32, approvedCount uint32, keeperRegistry common.Address, minLINKJuels *big.Int) error { + _, err := f.client.Decode(f.registrarMock.SetRegistrationConfig(f.client.NewTXOpts(), autoApproveConfigType, autoApproveMaxAllowed, approvedCount, keeperRegistry, minLINKJuels)) + return err +} + +func DeployKeeperRegistrar12Mock(client *seth.Client) (KeeperRegistrar12Mock, error) { + abi, err := keeper_registrar_wrapper1_2_mock.KeeperRegistrarMockMetaData.GetAbi() + if err != nil { + return &EthereumKeeperRegistrar12Mock{}, fmt.Errorf("failed to get KeeperRegistrar12Mock ABI: %w", err) + } + client.ContractStore.AddABI("KeeperRegistrar12Mock", *abi) + client.ContractStore.AddBIN("KeeperRegistrar12Mock", common.FromHex(keeper_registrar_wrapper1_2_mock.KeeperRegistrarMockMetaData.Bin)) + + data, err := client.DeployContract(client.NewTXOpts(), "KeeperRegistrar12Mock", *abi, common.FromHex(keeper_registrar_wrapper1_2_mock.KeeperRegistrarMockMetaData.Bin)) + + if err != nil { + return &EthereumKeeperRegistrar12Mock{}, fmt.Errorf("KeeperRegistrar12Mock instance deployment have failed: %w", err) + } + + instance, err := keeper_registrar_wrapper1_2_mock.NewKeeperRegistrarMock(data.Address, wrappers.MustNewWrappedContractBackend(nil, client)) + if err != nil { + return &EthereumKeeperRegistrar12Mock{}, fmt.Errorf("failed to instantiate KeeperRegistrar12Mock instance: %w", err) + } + + return &EthereumKeeperRegistrar12Mock{ + client: client, + registrarMock: instance, + address: &data.Address, + }, nil +} + +// EthereumKeeperGasWrapperMock represents the basic keeper gas wrapper mock contract +type EthereumKeeperGasWrapperMock struct { + client *seth.Client + gasWrapperMock *gas_wrapper_mock.KeeperRegistryCheckUpkeepGasUsageWrapperMock + address *common.Address +} + +func (f *EthereumKeeperGasWrapperMock) Address() string { + return f.address.Hex() +} + +func (f *EthereumKeeperGasWrapperMock) SetMeasureCheckGasResult(result bool, payload []byte, gas *big.Int) error { + _, err := f.client.Decode(f.gasWrapperMock.SetMeasureCheckGasResult(f.client.NewTXOpts(), result, payload, gas)) + return err +} + +func DeployKeeperGasWrapperMock(client *seth.Client) (KeeperGasWrapperMock, error) { + abi, err := gas_wrapper_mock.KeeperRegistryCheckUpkeepGasUsageWrapperMockMetaData.GetAbi() + if err != nil { + return &EthereumKeeperGasWrapperMock{}, fmt.Errorf("failed to get KeeperGasWrapperMock ABI: %w", err) + } + client.ContractStore.AddABI("KeeperGasWrapperMock", *abi) + client.ContractStore.AddBIN("KeeperGasWrapperMock", common.FromHex(gas_wrapper_mock.KeeperRegistryCheckUpkeepGasUsageWrapperMockMetaData.Bin)) + + data, err := client.DeployContract(client.NewTXOpts(), "KeeperGasWrapperMock", *abi, common.FromHex(gas_wrapper_mock.KeeperRegistryCheckUpkeepGasUsageWrapperMockMetaData.Bin)) + + if err != nil { + return &EthereumKeeperGasWrapperMock{}, fmt.Errorf("KeeperGasWrapperMock instance deployment have failed: %w", err) + } + + instance, err := gas_wrapper_mock.NewKeeperRegistryCheckUpkeepGasUsageWrapperMock(data.Address, wrappers.MustNewWrappedContractBackend(nil, client)) + if err != nil { + return &EthereumKeeperGasWrapperMock{}, fmt.Errorf("failed to instantiate KeeperGasWrapperMock instance: %w", err) + } + + return &EthereumKeeperGasWrapperMock{ + client: client, + gasWrapperMock: instance, + address: &data.Address, + }, nil +} + +// EthereumStakingEventsMock represents the basic events mock contract +type EthereumStakingEventsMock struct { + client *seth.Client + eventsMock *eth_contracts.StakingEventsMock + address *common.Address +} + +func (f *EthereumStakingEventsMock) Address() string { + return f.address.Hex() +} + +func (f *EthereumStakingEventsMock) MaxCommunityStakeAmountIncreased(maxStakeAmount *big.Int) error { + _, err := f.client.Decode(f.eventsMock.EmitMaxCommunityStakeAmountIncreased(f.client.NewTXOpts(), maxStakeAmount)) + return err +} + +func (f *EthereumStakingEventsMock) PoolSizeIncreased(maxPoolSize *big.Int) error { + _, err := f.client.Decode(f.eventsMock.EmitPoolSizeIncreased(f.client.NewTXOpts(), maxPoolSize)) + return err +} + +func (f *EthereumStakingEventsMock) MaxOperatorStakeAmountIncreased(maxStakeAmount *big.Int) error { + _, err := f.client.Decode(f.eventsMock.EmitMaxOperatorStakeAmountIncreased(f.client.NewTXOpts(), maxStakeAmount)) + return err +} + +func (f *EthereumStakingEventsMock) RewardInitialized(rate *big.Int, available *big.Int, startTimestamp *big.Int, endTimestamp *big.Int) error { + _, err := f.client.Decode(f.eventsMock.EmitRewardInitialized(f.client.NewTXOpts(), rate, available, startTimestamp, endTimestamp)) + return err +} + +func (f *EthereumStakingEventsMock) AlertRaised(alerter common.Address, roundId *big.Int, rewardAmount *big.Int) error { + _, err := f.client.Decode(f.eventsMock.EmitAlertRaised(f.client.NewTXOpts(), alerter, roundId, rewardAmount)) + return err +} + +func (f *EthereumStakingEventsMock) Staked(staker common.Address, newStake *big.Int, totalStake *big.Int) error { + _, err := f.client.Decode(f.eventsMock.EmitStaked(f.client.NewTXOpts(), staker, newStake, totalStake)) + return err +} + +func (f *EthereumStakingEventsMock) OperatorAdded(operator common.Address) error { + _, err := f.client.Decode(f.eventsMock.EmitOperatorAdded(f.client.NewTXOpts(), operator)) + return err +} + +func (f *EthereumStakingEventsMock) OperatorRemoved(operator common.Address, amount *big.Int) error { + _, err := f.client.Decode(f.eventsMock.EmitOperatorRemoved(f.client.NewTXOpts(), operator, amount)) + return err +} + +func (f *EthereumStakingEventsMock) FeedOperatorsSet(feedOperators []common.Address) error { + _, err := f.client.Decode(f.eventsMock.EmitFeedOperatorsSet(f.client.NewTXOpts(), feedOperators)) + return err +} + +func DeployStakingEventsMock(client *seth.Client) (StakingEventsMock, error) { + abi, err := eth_contracts.StakingEventsMockMetaData.GetAbi() + if err != nil { + return &EthereumStakingEventsMock{}, fmt.Errorf("failed to get StakingEventsMock ABI: %w", err) + } + client.ContractStore.AddABI("StakingEventsMock", *abi) + client.ContractStore.AddBIN("StakingEventsMock", common.FromHex(eth_contracts.StakingEventsMockMetaData.Bin)) + + data, err := client.DeployContract(client.NewTXOpts(), "StakingEventsMock", *abi, common.FromHex(eth_contracts.StakingEventsMockMetaData.Bin)) + + if err != nil { + return &EthereumStakingEventsMock{}, fmt.Errorf("StakingEventsMock instance deployment have failed: %w", err) + } + + instance, err := eth_contracts.NewStakingEventsMock(data.Address, wrappers.MustNewWrappedContractBackend(nil, client)) + if err != nil { + return &EthereumStakingEventsMock{}, fmt.Errorf("failed to instantiate StakingEventsMock instance: %w", err) + } + + return &EthereumStakingEventsMock{ + client: client, + eventsMock: instance, + address: &data.Address, + }, nil +} diff --git a/integration-tests/contracts/ethereum_contracts.go b/integration-tests/contracts/ethereum_contracts.go index e8b2f184ce9..adf4dcffe80 100644 --- a/integration-tests/contracts/ethereum_contracts.go +++ b/integration-tests/contracts/ethereum_contracts.go @@ -350,18 +350,18 @@ func (f *EthereumFunctionsBillingRegistryEventsMock) BillingEnd(requestId [32]by return f.client.ProcessTransaction(tx) } -// EthereumStakingEventsMock represents the basic events mock contract -type EthereumStakingEventsMock struct { +// LegacyEthereumStakingEventsMock represents the basic events mock contract +type LegacyEthereumStakingEventsMock struct { client blockchain.EVMClient eventsMock *eth_contracts.StakingEventsMock address *common.Address } -func (f *EthereumStakingEventsMock) Address() string { +func (f *LegacyEthereumStakingEventsMock) Address() string { return f.address.Hex() } -func (f *EthereumStakingEventsMock) MaxCommunityStakeAmountIncreased(maxStakeAmount *big.Int) error { +func (f *LegacyEthereumStakingEventsMock) MaxCommunityStakeAmountIncreased(maxStakeAmount *big.Int) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -373,7 +373,7 @@ func (f *EthereumStakingEventsMock) MaxCommunityStakeAmountIncreased(maxStakeAmo return f.client.ProcessTransaction(tx) } -func (f *EthereumStakingEventsMock) PoolSizeIncreased(maxPoolSize *big.Int) error { +func (f *LegacyEthereumStakingEventsMock) PoolSizeIncreased(maxPoolSize *big.Int) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -385,7 +385,7 @@ func (f *EthereumStakingEventsMock) PoolSizeIncreased(maxPoolSize *big.Int) erro return f.client.ProcessTransaction(tx) } -func (f *EthereumStakingEventsMock) MaxOperatorStakeAmountIncreased(maxStakeAmount *big.Int) error { +func (f *LegacyEthereumStakingEventsMock) MaxOperatorStakeAmountIncreased(maxStakeAmount *big.Int) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -397,7 +397,7 @@ func (f *EthereumStakingEventsMock) MaxOperatorStakeAmountIncreased(maxStakeAmou return f.client.ProcessTransaction(tx) } -func (f *EthereumStakingEventsMock) RewardInitialized(rate *big.Int, available *big.Int, startTimestamp *big.Int, endTimestamp *big.Int) error { +func (f *LegacyEthereumStakingEventsMock) RewardInitialized(rate *big.Int, available *big.Int, startTimestamp *big.Int, endTimestamp *big.Int) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -409,7 +409,7 @@ func (f *EthereumStakingEventsMock) RewardInitialized(rate *big.Int, available * return f.client.ProcessTransaction(tx) } -func (f *EthereumStakingEventsMock) AlertRaised(alerter common.Address, roundId *big.Int, rewardAmount *big.Int) error { +func (f *LegacyEthereumStakingEventsMock) AlertRaised(alerter common.Address, roundId *big.Int, rewardAmount *big.Int) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -421,7 +421,7 @@ func (f *EthereumStakingEventsMock) AlertRaised(alerter common.Address, roundId return f.client.ProcessTransaction(tx) } -func (f *EthereumStakingEventsMock) Staked(staker common.Address, newStake *big.Int, totalStake *big.Int) error { +func (f *LegacyEthereumStakingEventsMock) Staked(staker common.Address, newStake *big.Int, totalStake *big.Int) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -433,7 +433,7 @@ func (f *EthereumStakingEventsMock) Staked(staker common.Address, newStake *big. return f.client.ProcessTransaction(tx) } -func (f *EthereumStakingEventsMock) OperatorAdded(operator common.Address) error { +func (f *LegacyEthereumStakingEventsMock) OperatorAdded(operator common.Address) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -445,7 +445,7 @@ func (f *EthereumStakingEventsMock) OperatorAdded(operator common.Address) error return f.client.ProcessTransaction(tx) } -func (f *EthereumStakingEventsMock) OperatorRemoved(operator common.Address, amount *big.Int) error { +func (f *LegacyEthereumStakingEventsMock) OperatorRemoved(operator common.Address, amount *big.Int) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -457,7 +457,7 @@ func (f *EthereumStakingEventsMock) OperatorRemoved(operator common.Address, amo return f.client.ProcessTransaction(tx) } -func (f *EthereumStakingEventsMock) FeedOperatorsSet(feedOperators []common.Address) error { +func (f *LegacyEthereumStakingEventsMock) FeedOperatorsSet(feedOperators []common.Address) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -504,18 +504,18 @@ func (f *EthereumOffchainAggregatorEventsMock) NewTransmission(aggregatorRoundId return f.client.ProcessTransaction(tx) } -// EthereumKeeperRegistry11Mock represents the basic keeper registry 1.1 mock contract -type EthereumKeeperRegistry11Mock struct { +// LegacyEthereumKeeperRegistry11Mock represents the basic keeper registry 1.1 mock contract +type LegacyEthereumKeeperRegistry11Mock struct { client blockchain.EVMClient registryMock *keeper_registry_wrapper1_1_mock.KeeperRegistryMock address *common.Address } -func (f *EthereumKeeperRegistry11Mock) Address() string { +func (f *LegacyEthereumKeeperRegistry11Mock) Address() string { return f.address.Hex() } -func (f *EthereumKeeperRegistry11Mock) EmitUpkeepPerformed(id *big.Int, success bool, from common.Address, payment *big.Int, performData []byte) error { +func (f *LegacyEthereumKeeperRegistry11Mock) EmitUpkeepPerformed(id *big.Int, success bool, from common.Address, payment *big.Int, performData []byte) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -527,7 +527,7 @@ func (f *EthereumKeeperRegistry11Mock) EmitUpkeepPerformed(id *big.Int, success return f.client.ProcessTransaction(tx) } -func (f *EthereumKeeperRegistry11Mock) EmitUpkeepCanceled(id *big.Int, atBlockHeight uint64) error { +func (f *LegacyEthereumKeeperRegistry11Mock) EmitUpkeepCanceled(id *big.Int, atBlockHeight uint64) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -539,7 +539,7 @@ func (f *EthereumKeeperRegistry11Mock) EmitUpkeepCanceled(id *big.Int, atBlockHe return f.client.ProcessTransaction(tx) } -func (f *EthereumKeeperRegistry11Mock) EmitFundsWithdrawn(id *big.Int, amount *big.Int, to common.Address) error { +func (f *LegacyEthereumKeeperRegistry11Mock) EmitFundsWithdrawn(id *big.Int, amount *big.Int, to common.Address) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -551,7 +551,7 @@ func (f *EthereumKeeperRegistry11Mock) EmitFundsWithdrawn(id *big.Int, amount *b return f.client.ProcessTransaction(tx) } -func (f *EthereumKeeperRegistry11Mock) EmitKeepersUpdated(keepers []common.Address, payees []common.Address) error { +func (f *LegacyEthereumKeeperRegistry11Mock) EmitKeepersUpdated(keepers []common.Address, payees []common.Address) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -563,7 +563,7 @@ func (f *EthereumKeeperRegistry11Mock) EmitKeepersUpdated(keepers []common.Addre return f.client.ProcessTransaction(tx) } -func (f *EthereumKeeperRegistry11Mock) EmitUpkeepRegistered(id *big.Int, executeGas uint32, admin common.Address) error { +func (f *LegacyEthereumKeeperRegistry11Mock) EmitUpkeepRegistered(id *big.Int, executeGas uint32, admin common.Address) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -575,7 +575,7 @@ func (f *EthereumKeeperRegistry11Mock) EmitUpkeepRegistered(id *big.Int, execute return f.client.ProcessTransaction(tx) } -func (f *EthereumKeeperRegistry11Mock) EmitFundsAdded(id *big.Int, from common.Address, amount *big.Int) error { +func (f *LegacyEthereumKeeperRegistry11Mock) EmitFundsAdded(id *big.Int, from common.Address, amount *big.Int) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -587,7 +587,7 @@ func (f *EthereumKeeperRegistry11Mock) EmitFundsAdded(id *big.Int, from common.A return f.client.ProcessTransaction(tx) } -func (f *EthereumKeeperRegistry11Mock) SetUpkeepCount(_upkeepCount *big.Int) error { +func (f *LegacyEthereumKeeperRegistry11Mock) SetUpkeepCount(_upkeepCount *big.Int) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -599,7 +599,7 @@ func (f *EthereumKeeperRegistry11Mock) SetUpkeepCount(_upkeepCount *big.Int) err return f.client.ProcessTransaction(tx) } -func (f *EthereumKeeperRegistry11Mock) SetCanceledUpkeepList(_canceledUpkeepList []*big.Int) error { +func (f *LegacyEthereumKeeperRegistry11Mock) SetCanceledUpkeepList(_canceledUpkeepList []*big.Int) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -611,7 +611,7 @@ func (f *EthereumKeeperRegistry11Mock) SetCanceledUpkeepList(_canceledUpkeepList return f.client.ProcessTransaction(tx) } -func (f *EthereumKeeperRegistry11Mock) SetKeeperList(_keepers []common.Address) error { +func (f *LegacyEthereumKeeperRegistry11Mock) SetKeeperList(_keepers []common.Address) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -623,7 +623,7 @@ func (f *EthereumKeeperRegistry11Mock) SetKeeperList(_keepers []common.Address) return f.client.ProcessTransaction(tx) } -func (f *EthereumKeeperRegistry11Mock) SetConfig(_paymentPremiumPPB uint32, _flatFeeMicroLink uint32, _blockCountPerTurn *big.Int, _checkGasLimit uint32, _stalenessSeconds *big.Int, _gasCeilingMultiplier uint16, _fallbackGasPrice *big.Int, _fallbackLinkPrice *big.Int) error { +func (f *LegacyEthereumKeeperRegistry11Mock) SetConfig(_paymentPremiumPPB uint32, _flatFeeMicroLink uint32, _blockCountPerTurn *big.Int, _checkGasLimit uint32, _stalenessSeconds *big.Int, _gasCeilingMultiplier uint16, _fallbackGasPrice *big.Int, _fallbackLinkPrice *big.Int) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -635,7 +635,7 @@ func (f *EthereumKeeperRegistry11Mock) SetConfig(_paymentPremiumPPB uint32, _fla return f.client.ProcessTransaction(tx) } -func (f *EthereumKeeperRegistry11Mock) SetUpkeep(id *big.Int, _target common.Address, _executeGas uint32, _balance *big.Int, _admin common.Address, _maxValidBlocknumber uint64, _lastKeeper common.Address, _checkData []byte) error { +func (f *LegacyEthereumKeeperRegistry11Mock) SetUpkeep(id *big.Int, _target common.Address, _executeGas uint32, _balance *big.Int, _admin common.Address, _maxValidBlocknumber uint64, _lastKeeper common.Address, _checkData []byte) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -647,7 +647,7 @@ func (f *EthereumKeeperRegistry11Mock) SetUpkeep(id *big.Int, _target common.Add return f.client.ProcessTransaction(tx) } -func (f *EthereumKeeperRegistry11Mock) SetMinBalance(id *big.Int, minBalance *big.Int) error { +func (f *LegacyEthereumKeeperRegistry11Mock) SetMinBalance(id *big.Int, minBalance *big.Int) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -659,7 +659,7 @@ func (f *EthereumKeeperRegistry11Mock) SetMinBalance(id *big.Int, minBalance *bi return f.client.ProcessTransaction(tx) } -func (f *EthereumKeeperRegistry11Mock) SetCheckUpkeepData(id *big.Int, performData []byte, maxLinkPayment *big.Int, gasLimit *big.Int, adjustedGasWei *big.Int, linkEth *big.Int) error { +func (f *LegacyEthereumKeeperRegistry11Mock) SetCheckUpkeepData(id *big.Int, performData []byte, maxLinkPayment *big.Int, gasLimit *big.Int, adjustedGasWei *big.Int, linkEth *big.Int) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -671,7 +671,7 @@ func (f *EthereumKeeperRegistry11Mock) SetCheckUpkeepData(id *big.Int, performDa return f.client.ProcessTransaction(tx) } -func (f *EthereumKeeperRegistry11Mock) SetPerformUpkeepSuccess(id *big.Int, success bool) error { +func (f *LegacyEthereumKeeperRegistry11Mock) SetPerformUpkeepSuccess(id *big.Int, success bool) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -683,18 +683,18 @@ func (f *EthereumKeeperRegistry11Mock) SetPerformUpkeepSuccess(id *big.Int, succ return f.client.ProcessTransaction(tx) } -// EthereumKeeperRegistrar12Mock represents the basic keeper registrar 1.2 mock contract -type EthereumKeeperRegistrar12Mock struct { +// LegacyEthereumKeeperRegistrar12Mock represents the basic keeper registrar 1.2 mock contract +type LegacyEthereumKeeperRegistrar12Mock struct { client blockchain.EVMClient registrarMock *keeper_registrar_wrapper1_2_mock.KeeperRegistrarMock address *common.Address } -func (f *EthereumKeeperRegistrar12Mock) Address() string { +func (f *LegacyEthereumKeeperRegistrar12Mock) Address() string { return f.address.Hex() } -func (f *EthereumKeeperRegistrar12Mock) EmitRegistrationRequested(hash [32]byte, name string, encryptedEmail []byte, upkeepContract common.Address, gasLimit uint32, adminAddress common.Address, checkData []byte, amount *big.Int, source uint8) error { +func (f *LegacyEthereumKeeperRegistrar12Mock) EmitRegistrationRequested(hash [32]byte, name string, encryptedEmail []byte, upkeepContract common.Address, gasLimit uint32, adminAddress common.Address, checkData []byte, amount *big.Int, source uint8) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -706,7 +706,7 @@ func (f *EthereumKeeperRegistrar12Mock) EmitRegistrationRequested(hash [32]byte, return f.client.ProcessTransaction(tx) } -func (f *EthereumKeeperRegistrar12Mock) EmitRegistrationApproved(hash [32]byte, displayName string, upkeepId *big.Int) error { +func (f *LegacyEthereumKeeperRegistrar12Mock) EmitRegistrationApproved(hash [32]byte, displayName string, upkeepId *big.Int) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -718,7 +718,7 @@ func (f *EthereumKeeperRegistrar12Mock) EmitRegistrationApproved(hash [32]byte, return f.client.ProcessTransaction(tx) } -func (f *EthereumKeeperRegistrar12Mock) SetRegistrationConfig(_autoApproveConfigType uint8, _autoApproveMaxAllowed uint32, _approvedCount uint32, _keeperRegistry common.Address, _minLINKJuels *big.Int) error { +func (f *LegacyEthereumKeeperRegistrar12Mock) SetRegistrationConfig(_autoApproveConfigType uint8, _autoApproveMaxAllowed uint32, _approvedCount uint32, _keeperRegistry common.Address, _minLINKJuels *big.Int) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -730,18 +730,18 @@ func (f *EthereumKeeperRegistrar12Mock) SetRegistrationConfig(_autoApproveConfig return f.client.ProcessTransaction(tx) } -// EthereumKeeperGasWrapperMock represents the basic keeper gas wrapper mock contract -type EthereumKeeperGasWrapperMock struct { +// LegacyEthereumKeeperGasWrapperMock represents the basic keeper gas wrapper mock contract +type LegacyEthereumKeeperGasWrapperMock struct { client blockchain.EVMClient gasWrapperMock *gas_wrapper_mock.KeeperRegistryCheckUpkeepGasUsageWrapperMock address *common.Address } -func (f *EthereumKeeperGasWrapperMock) Address() string { +func (f *LegacyEthereumKeeperGasWrapperMock) Address() string { return f.address.Hex() } -func (f *EthereumKeeperGasWrapperMock) SetMeasureCheckGasResult(result bool, payload []byte, gas *big.Int) error { +func (f *LegacyEthereumKeeperGasWrapperMock) SetMeasureCheckGasResult(result bool, payload []byte, gas *big.Int) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -753,18 +753,18 @@ func (f *EthereumKeeperGasWrapperMock) SetMeasureCheckGasResult(result bool, pay return f.client.ProcessTransaction(tx) } -// EthereumFunctionsV1EventsMock represents the basic functions v1 events mock contract -type EthereumFunctionsV1EventsMock struct { +// LegacyEthereumFunctionsV1EventsMock represents the basic functions v1 events mock contract +type LegacyEthereumFunctionsV1EventsMock struct { client blockchain.EVMClient eventsMock *functions_v1_events_mock.FunctionsV1EventsMock address *common.Address } -func (f *EthereumFunctionsV1EventsMock) Address() string { +func (f *LegacyEthereumFunctionsV1EventsMock) Address() string { return f.address.Hex() } -func (f *EthereumFunctionsV1EventsMock) EmitRequestProcessed(requestId [32]byte, subscriptionId uint64, totalCostJuels *big.Int, transmitter common.Address, resultCode uint8, response []byte, errByte []byte, callbackReturnData []byte) error { +func (f *LegacyEthereumFunctionsV1EventsMock) EmitRequestProcessed(requestId [32]byte, subscriptionId uint64, totalCostJuels *big.Int, transmitter common.Address, resultCode uint8, response []byte, errByte []byte, callbackReturnData []byte) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -776,7 +776,7 @@ func (f *EthereumFunctionsV1EventsMock) EmitRequestProcessed(requestId [32]byte, return f.client.ProcessTransaction(tx) } -func (f *EthereumFunctionsV1EventsMock) EmitRequestStart(requestId [32]byte, donId [32]byte, subscriptionId uint64, subscriptionOwner common.Address, requestingContract common.Address, requestInitiator common.Address, data []byte, dataVersion uint16, callbackGasLimit uint32, estimatedTotalCostJuels *big.Int) error { +func (f *LegacyEthereumFunctionsV1EventsMock) EmitRequestStart(requestId [32]byte, donId [32]byte, subscriptionId uint64, subscriptionOwner common.Address, requestingContract common.Address, requestInitiator common.Address, data []byte, dataVersion uint16, callbackGasLimit uint32, estimatedTotalCostJuels *big.Int) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -788,7 +788,7 @@ func (f *EthereumFunctionsV1EventsMock) EmitRequestStart(requestId [32]byte, don return f.client.ProcessTransaction(tx) } -func (f *EthereumFunctionsV1EventsMock) EmitSubscriptionCanceled(subscriptionId uint64, fundsRecipient common.Address, fundsAmount *big.Int) error { +func (f *LegacyEthereumFunctionsV1EventsMock) EmitSubscriptionCanceled(subscriptionId uint64, fundsRecipient common.Address, fundsAmount *big.Int) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -800,7 +800,7 @@ func (f *EthereumFunctionsV1EventsMock) EmitSubscriptionCanceled(subscriptionId return f.client.ProcessTransaction(tx) } -func (f *EthereumFunctionsV1EventsMock) EmitSubscriptionConsumerAdded(subscriptionId uint64, consumer common.Address) error { +func (f *LegacyEthereumFunctionsV1EventsMock) EmitSubscriptionConsumerAdded(subscriptionId uint64, consumer common.Address) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -812,7 +812,7 @@ func (f *EthereumFunctionsV1EventsMock) EmitSubscriptionConsumerAdded(subscripti return f.client.ProcessTransaction(tx) } -func (f *EthereumFunctionsV1EventsMock) EmitSubscriptionConsumerRemoved(subscriptionId uint64, consumer common.Address) error { +func (f *LegacyEthereumFunctionsV1EventsMock) EmitSubscriptionConsumerRemoved(subscriptionId uint64, consumer common.Address) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -824,7 +824,7 @@ func (f *EthereumFunctionsV1EventsMock) EmitSubscriptionConsumerRemoved(subscrip return f.client.ProcessTransaction(tx) } -func (f *EthereumFunctionsV1EventsMock) EmitSubscriptionCreated(subscriptionId uint64, owner common.Address) error { +func (f *LegacyEthereumFunctionsV1EventsMock) EmitSubscriptionCreated(subscriptionId uint64, owner common.Address) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -836,7 +836,7 @@ func (f *EthereumFunctionsV1EventsMock) EmitSubscriptionCreated(subscriptionId u return f.client.ProcessTransaction(tx) } -func (f *EthereumFunctionsV1EventsMock) EmitSubscriptionFunded(subscriptionId uint64, oldBalance *big.Int, newBalance *big.Int) error { +func (f *LegacyEthereumFunctionsV1EventsMock) EmitSubscriptionFunded(subscriptionId uint64, oldBalance *big.Int, newBalance *big.Int) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -848,7 +848,7 @@ func (f *EthereumFunctionsV1EventsMock) EmitSubscriptionFunded(subscriptionId ui return f.client.ProcessTransaction(tx) } -func (f *EthereumFunctionsV1EventsMock) EmitSubscriptionOwnerTransferred(subscriptionId uint64, from common.Address, to common.Address) error { +func (f *LegacyEthereumFunctionsV1EventsMock) EmitSubscriptionOwnerTransferred(subscriptionId uint64, from common.Address, to common.Address) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -860,7 +860,7 @@ func (f *EthereumFunctionsV1EventsMock) EmitSubscriptionOwnerTransferred(subscri return f.client.ProcessTransaction(tx) } -func (f *EthereumFunctionsV1EventsMock) EmitSubscriptionOwnerTransferRequested(subscriptionId uint64, from common.Address, to common.Address) error { +func (f *LegacyEthereumFunctionsV1EventsMock) EmitSubscriptionOwnerTransferRequested(subscriptionId uint64, from common.Address, to common.Address) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -872,7 +872,7 @@ func (f *EthereumFunctionsV1EventsMock) EmitSubscriptionOwnerTransferRequested(s return f.client.ProcessTransaction(tx) } -func (f *EthereumFunctionsV1EventsMock) EmitRequestNotProcessed(requestId [32]byte, coordinator common.Address, transmitter common.Address, resultCode uint8) error { +func (f *LegacyEthereumFunctionsV1EventsMock) EmitRequestNotProcessed(requestId [32]byte, coordinator common.Address, transmitter common.Address, resultCode uint8) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err @@ -884,7 +884,7 @@ func (f *EthereumFunctionsV1EventsMock) EmitRequestNotProcessed(requestId [32]by return f.client.ProcessTransaction(tx) } -func (f *EthereumFunctionsV1EventsMock) EmitContractUpdated(id [32]byte, from common.Address, to common.Address) error { +func (f *LegacyEthereumFunctionsV1EventsMock) EmitContractUpdated(id [32]byte, from common.Address, to common.Address) error { opts, err := f.client.TransactionOpts(f.client.GetDefaultWallet()) if err != nil { return err diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 0903711f16e..3d76a656be5 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -26,11 +26,11 @@ require ( github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.3 github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb - github.com/smartcontractkit/chainlink-testing-framework v1.28.4 + github.com/smartcontractkit/chainlink-testing-framework v1.28.7 github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c - github.com/smartcontractkit/seth v0.1.6 + github.com/smartcontractkit/seth v0.1.6-0.20240429143720-cacb8160ecec github.com/smartcontractkit/wasp v0.4.5 github.com/spf13/cobra v1.8.0 github.com/stretchr/testify v1.9.0 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index d9bb628d861..61fef05bbad 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1529,8 +1529,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba5 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba58/go.mod h1:oV5gIuSKrPEcjQ6uB6smBsm5kXHxyydVLNyAs4V9CoQ= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595 h1:y6ks0HsSOhPUueOmTcoxDQ50RCS1XINlRDTemZyHjFw= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595/go.mod h1:vV6WfnVIbK5Q1JsIru4YcTG0T1uRpLJm6t2BgCnCSsg= -github.com/smartcontractkit/chainlink-testing-framework v1.28.4 h1:/OOPH76VFQlG5HEXrXgBVDv1fjuasQzMV1EyeaaXWzM= -github.com/smartcontractkit/chainlink-testing-framework v1.28.4/go.mod h1:jN+HgXbriq6fKRlIqLw9F3I81aYImV6kBJkIfz0mdIA= +github.com/smartcontractkit/chainlink-testing-framework v1.28.7 h1:Yr93tBl5jVx1cfKywt0C0cbuObDPJ6JIU4FIsZ6bZlM= +github.com/smartcontractkit/chainlink-testing-framework v1.28.7/go.mod h1:x1zDOz8zcLjEvs9fNA9y/DMguLam/2+CJdpxX0+rM8A= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= @@ -1539,8 +1539,8 @@ github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJ github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c h1:lIyMbTaF2H0Q71vkwZHX/Ew4KF2BxiKhqEXwF8rn+KI= github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= -github.com/smartcontractkit/seth v0.1.6 h1:exU96KiKM/gxvp7OR8KkOXnTgbtFNepdhMBvyobFKCw= -github.com/smartcontractkit/seth v0.1.6/go.mod h1:2TMOZQ8WTAw7rR1YBbXpnad6VmT/+xDd/nXLmB7Eero= +github.com/smartcontractkit/seth v0.1.6-0.20240429143720-cacb8160ecec h1:BT1loU6TT2YqMenD7XE+aw7IeeTiC25+r1TLKAySVIg= +github.com/smartcontractkit/seth v0.1.6-0.20240429143720-cacb8160ecec/go.mod h1:2TMOZQ8WTAw7rR1YBbXpnad6VmT/+xDd/nXLmB7Eero= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index a4c5b67c204..c8fde175cab 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -17,7 +17,7 @@ require ( github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.3 github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb - github.com/smartcontractkit/chainlink-testing-framework v1.28.4 + github.com/smartcontractkit/chainlink-testing-framework v1.28.7 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index e2d5b5270ff..46646e6b289 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1512,8 +1512,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba5 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba58/go.mod h1:oV5gIuSKrPEcjQ6uB6smBsm5kXHxyydVLNyAs4V9CoQ= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595 h1:y6ks0HsSOhPUueOmTcoxDQ50RCS1XINlRDTemZyHjFw= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595/go.mod h1:vV6WfnVIbK5Q1JsIru4YcTG0T1uRpLJm6t2BgCnCSsg= -github.com/smartcontractkit/chainlink-testing-framework v1.28.4 h1:/OOPH76VFQlG5HEXrXgBVDv1fjuasQzMV1EyeaaXWzM= -github.com/smartcontractkit/chainlink-testing-framework v1.28.4/go.mod h1:jN+HgXbriq6fKRlIqLw9F3I81aYImV6kBJkIfz0mdIA= +github.com/smartcontractkit/chainlink-testing-framework v1.28.7 h1:Yr93tBl5jVx1cfKywt0C0cbuObDPJ6JIU4FIsZ6bZlM= +github.com/smartcontractkit/chainlink-testing-framework v1.28.7/go.mod h1:x1zDOz8zcLjEvs9fNA9y/DMguLam/2+CJdpxX0+rM8A= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240227164431-18a7065e23ea h1:ZdLmNAfKRjH8AYUvjiiDGUgiWQfq/7iNpxyTkvjx/ko= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240227164431-18a7065e23ea/go.mod h1:gCKC9w6XpNk6jm+XIk2psrkkfxhi421N9NSiFceXW88= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= From 8cb83a4d553fa425aec67269d56f12f0efcc4a92 Mon Sep 17 00:00:00 2001 From: frank zhu Date: Mon, 29 Apr 2024 10:19:33 -0700 Subject: [PATCH 07/45] add version to changeset release preview pr (#13032) * add version to changeset release preview pr * add more perm for gh token * add GITHUB_TOKEN env to run changeset version * add workflow perm * workflows * test new perm * fix github_output bug and remove a perm * remove test branch trigger * remove test changeset --- .github/workflows/cicd-changesets.yml | 28 ++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cicd-changesets.yml b/.github/workflows/cicd-changesets.yml index 0bfec7b22f2..96363588319 100644 --- a/.github/workflows/cicd-changesets.yml +++ b/.github/workflows/cicd-changesets.yml @@ -16,6 +16,7 @@ jobs: permissions: id-token: write contents: read + actions: read steps: - name: Checkout repository uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 @@ -28,6 +29,31 @@ jobs: core-changeset: - added: '.changeset/**' + - name: Setup pnpm + uses: pnpm/action-setup@a3252b78c470c02df07e9d59298aecedc3ccdd6d # v3.0.0 + if: steps.changeset-added.outputs.core-changeset == 'true' + with: + version: ^8.0.0 + + - name: Setup node + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + if: steps.changeset-added.outputs.core-changeset == 'true' + with: + node-version: 20 + cache: pnpm + cache-dependency-path: ./pnpm-lock.yaml + + - name: Run changeset version + run: pnpm install && pnpm changeset version + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + if: steps.changeset-added.outputs.core-changeset == 'true' + + - name: Get release version + if: steps.changeset-added.outputs.core-changeset == 'true' + id: get-release-version + run: echo "version=$(jq -r '.version' package.json)" >> $GITHUB_OUTPUT + - name: cicd-changesets if: steps.changeset-added.outputs.core-changeset == 'true' uses: smartcontractkit/.github/actions/cicd-changesets@6da79c7b9f14bec077df2c1ad40d53823b409d9c # cicd-changesets@0.3.3 @@ -37,7 +63,7 @@ jobs: git-email: app-token-issuer-releng[bot]@users.noreply.github.com pnpm-use-cache: false pr-draft: true - pr-title: "[DO NOT MERGE] Release Preview - Changeset" + pr-title: "[DO NOT MERGE] Changeset Release Preview - v${{ steps.get-release-version.outputs.version }}" # aws inputs aws-region: ${{ secrets.AWS_REGION }} aws-role-arn: ${{ secrets.AWS_OIDC_CHAINLINK_CI_AUTO_PR_TOKEN_ISSUER_ROLE_ARN }} From e482c7982278e232acaaa4b3e9a79165faa35d1c Mon Sep 17 00:00:00 2001 From: HenryNguyen5 <6404866+HenryNguyen5@users.noreply.github.com> Date: Mon, 29 Apr 2024 19:46:47 -0400 Subject: [PATCH 08/45] [Keystone] Improve workflow engine test times (#12959) * Improve workflow engine test times * Extract graph traversal initalization logic --- .changeset/fast-students-accept.md | 5 + core/services/workflows/engine.go | 207 +++++++++++++--------- core/services/workflows/engine_test.go | 85 +++++---- core/services/workflows/retry.go | 53 ++++++ core/services/workflows/retryable_test.go | 113 ++++++++++++ 5 files changed, 339 insertions(+), 124 deletions(-) create mode 100644 .changeset/fast-students-accept.md create mode 100644 core/services/workflows/retry.go create mode 100644 core/services/workflows/retryable_test.go diff --git a/.changeset/fast-students-accept.md b/.changeset/fast-students-accept.md new file mode 100644 index 00000000000..8813f3a7812 --- /dev/null +++ b/.changeset/fast-students-accept.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal Optimize workflow engine tests diff --git a/core/services/workflows/engine.go b/core/services/workflows/engine.go index 0ecc311acac..040e123567e 100644 --- a/core/services/workflows/engine.go +++ b/core/services/workflows/engine.go @@ -45,6 +45,14 @@ type Engine struct { // Used for testing to wait for an execution to complete xxxExecutionFinished chan string + // testing lifecycle hook to signal initialization status + afterInit func(success bool) + // Used for testing to control the number of retries + // we'll do when initializing the engine. + maxRetries int + // Used for testing to control the retry interval + // when initializing the engine. + retryMs int } func (e *Engine) Start(ctx context.Context) error { @@ -60,94 +68,67 @@ func (e *Engine) Start(ctx context.Context) error { }) } -// init does the following: -// -// 1. Resolves the underlying capability for each trigger -// 2. Registers each step's capability to this workflow -// 3. Registers for trigger events now that all capabilities are resolved +// resolveWorkflowCapabilities does the following: // -// Steps 1 and 2 are retried every 5 seconds until successful. -func (e *Engine) init(ctx context.Context) { - defer e.wg.Done() - - retrySec := 5 - ticker := time.NewTicker(time.Duration(retrySec) * time.Second) - defer ticker.Stop() - -LOOP: - for { - select { - case <-ctx.Done(): - return - case <-ticker.C: - initSuccessful := true - // Resolve the underlying capability for each trigger - for _, t := range e.workflow.triggers { - tg, err := e.registry.GetTrigger(ctx, t.Type) - if err != nil { - initSuccessful = false - e.logger.Errorf("failed to get trigger capability: %s, retrying in %d seconds", err, retrySec) - continue - } - t.trigger = tg - } - if !initSuccessful { - continue - } - - // Walk the graph and initialize each step. - // This means: - // - fetching the capability - // - register the capability to this workflow - // - initializing the step's executionStrategy - err := e.workflow.walkDo(keywordTrigger, func(s *step) error { - // The graph contains a dummy step for triggers, but - // we handle triggers separately since there might be more than one. - if s.Ref == keywordTrigger { - return nil - } - - err := e.initializeCapability(ctx, s, retrySec) - if err != nil { - return err - } - - return e.initializeExecutionStrategy(s) - }) - if err != nil { - initSuccessful = false - e.logger.Error(err) - } - - if initSuccessful { - break LOOP - } +// 1. Resolves the underlying capability for each trigger +// 2. Registers each step's capability to this workflow +func (e *Engine) resolveWorkflowCapabilities(ctx context.Context) error { + // + // Step 1. Resolve the underlying capability for each trigger + // + triggersInitialized := true + for _, t := range e.workflow.triggers { + tg, err := e.registry.GetTrigger(ctx, t.Type) + if err != nil { + e.logger.Errorf("failed to get trigger capability: %s", err) + // we don't immediately return here, since we want to retry all triggers + // to notify the user of all errors at once. + triggersInitialized = false + } else { + t.trigger = tg } } + if !triggersInitialized { + return fmt.Errorf("failed to resolve triggers") + } + + // Step 2. Walk the graph and register each step's capability to this workflow + // + // This means: + // - fetching the capability + // - register the capability to this workflow + // - initializing the step's executionStrategy + capabilityRegistrationErr := e.workflow.walkDo(keywordTrigger, func(s *step) error { + // The graph contains a dummy step for triggers, but + // we handle triggers separately since there might be more than one + // trigger registered to a workflow. + if s.Ref == keywordTrigger { + return nil + } - // We have all needed capabilities, now we can register for trigger events - for _, t := range e.workflow.triggers { - err := e.registerTrigger(ctx, t) + err := e.initializeCapability(ctx, s) if err != nil { - e.logger.Errorf("failed to register trigger: %s", err) + return err } - } - e.logger.Info("engine initialized") + return e.initializeExecutionStrategy(s) + }) + + return capabilityRegistrationErr } -func (e *Engine) initializeCapability(ctx context.Context, s *step, retrySec int) error { +func (e *Engine) initializeCapability(ctx context.Context, s *step) error { // If the capability already exists, that means we've already registered it if s.capability != nil { return nil } - cp, innerErr := e.registry.Get(ctx, s.Type) - if innerErr != nil { - return fmt.Errorf("failed to get capability with ref %s: %s, retrying in %d seconds", s.Type, innerErr, retrySec) + cp, err := e.registry.Get(ctx, s.Type) + if err != nil { + return fmt.Errorf("failed to get capability with ref %s: %s", s.Type, err) } - // We only need to configure actions, consensus and targets here, and + // We configure actions, consensus and targets here, and // they all satisfy the `CallbackCapability` interface cc, ok := cp.(capabilities.CallbackCapability) if !ok { @@ -155,29 +136,65 @@ func (e *Engine) initializeCapability(ctx context.Context, s *step, retrySec int } if s.config == nil { - configMap, ierr := values.NewMap(s.Config) - if ierr != nil { - return fmt.Errorf("failed to convert config to values.Map: %s", ierr) + configMap, newMapErr := values.NewMap(s.Config) + if newMapErr != nil { + return fmt.Errorf("failed to convert config to values.Map: %s", newMapErr) } s.config = configMap } - reg := capabilities.RegisterToWorkflowRequest{ + registrationRequest := capabilities.RegisterToWorkflowRequest{ Metadata: capabilities.RegistrationMetadata{ WorkflowID: e.workflow.id, }, Config: s.config, } - innerErr = cc.RegisterToWorkflow(ctx, reg) - if innerErr != nil { - return fmt.Errorf("failed to register to workflow (%+v): %w", reg, innerErr) + err = cc.RegisterToWorkflow(ctx, registrationRequest) + if err != nil { + return fmt.Errorf("failed to register to workflow (%+v): %w", registrationRequest, err) } s.capability = cc return nil } +// init does the following: +// +// 1. Resolves the underlying capability for each trigger +// 2. Registers each step's capability to this workflow +// 3. Registers for trigger events now that all capabilities are resolved +// +// Steps 1 and 2 are retried every 5 seconds until successful. +func (e *Engine) init(ctx context.Context) { + defer e.wg.Done() + + retryErr := retryable(ctx, e.logger, e.retryMs, e.maxRetries, func() error { + err := e.resolveWorkflowCapabilities(ctx) + if err != nil { + return fmt.Errorf("failed to resolve workflow: %s", err) + } + return nil + }) + + if retryErr != nil { + e.logger.Errorf("initialization failed: %s", retryErr) + e.afterInit(false) + return + } + + e.logger.Debug("capabilities resolved, registering triggers") + for _, t := range e.workflow.triggers { + err := e.registerTrigger(ctx, t) + if err != nil { + e.logger.Errorf("failed to register trigger: %s", err) + } + } + + e.logger.Info("engine initialized") + e.afterInit(true) +} + // initializeExecutionStrategy for `step`. // Broadly speaking, we'll use `immediateExecution` for non-target steps // and `scheduledExecution` for targets. If we don't have the necessary @@ -609,6 +626,7 @@ func (e *Engine) deregisterTrigger(ctx context.Context, t *triggerCapability) er func (e *Engine) Close() error { return e.StopOnce("Engine", func() error { + e.logger.Info("shutting down engine") ctx := context.Background() // To shut down the engine, we'll start by deregistering // any triggers to ensure no new executions are triggered, @@ -668,6 +686,11 @@ type Config struct { NewWorkerTimeout time.Duration DONInfo *capabilities.DON PeerID func() *p2ptypes.PeerID + + // For testing purposes only + maxRetries int + retryMs int + afterInit func(success bool) } const ( @@ -689,6 +712,14 @@ func NewEngine(cfg Config) (engine *Engine, err error) { cfg.NewWorkerTimeout = defaultNewWorkerTimeout } + if cfg.retryMs == 0 { + cfg.retryMs = 5000 + } + + if cfg.afterInit == nil { + cfg.afterInit = func(success bool) {} + } + // TODO: validation of the workflow spec // We'll need to check, among other things: // - that there are no step `ref` called `trigger` as this is reserved for any triggers @@ -718,14 +749,18 @@ func NewEngine(cfg Config) (engine *Engine, err error) { DON: cfg.DONInfo, PeerID: cfg.PeerID, }, - executionStates: newInMemoryStore(), - pendingStepRequests: make(chan stepRequest, cfg.QueueSize), - newWorkerCh: newWorkerCh, - stepUpdateCh: make(chan stepState), - triggerEvents: make(chan capabilities.CapabilityResponse), - stopCh: make(chan struct{}), - newWorkerTimeout: cfg.NewWorkerTimeout, + executionStates: newInMemoryStore(), + pendingStepRequests: make(chan stepRequest, cfg.QueueSize), + newWorkerCh: newWorkerCh, + stepUpdateCh: make(chan stepState), + triggerEvents: make(chan capabilities.CapabilityResponse), + stopCh: make(chan struct{}), + newWorkerTimeout: cfg.NewWorkerTimeout, + // For testing purposes only xxxExecutionFinished: make(chan string), + afterInit: cfg.afterInit, + maxRetries: cfg.maxRetries, + retryMs: cfg.retryMs, } return engine, nil } diff --git a/core/services/workflows/engine_test.go b/core/services/workflows/engine_test.go index d82c9d4b7d2..4821b5800c7 100644 --- a/core/services/workflows/engine_test.go +++ b/core/services/workflows/engine_test.go @@ -65,6 +65,44 @@ targets: abi: "receive(report bytes)" ` +// newTestEngine creates a new engine with some test defaults. +func newTestEngine(t *testing.T, reg *coreCap.Registry, spec string) (eng *Engine, initFailed chan struct{}) { + peerID := p2ptypes.PeerID{} + initFailed = make(chan struct{}) + cfg := Config{ + Lggr: logger.TestLogger(t), + Registry: reg, + Spec: spec, + DONInfo: nil, + PeerID: func() *p2ptypes.PeerID { return &peerID }, + maxRetries: 1, + retryMs: 100, + afterInit: func(success bool) { + if !success { + close(initFailed) + } + }, + } + eng, err := NewEngine(cfg) + require.NoError(t, err) + return eng, initFailed +} + +// getExecutionId returns the execution id of the workflow that is +// currently being executed by the engine. +// +// If the engine fails to initialize, the test will fail rather +// than blocking indefinitely. +func getExecutionId(t *testing.T, eng *Engine, initFailed <-chan struct{}) string { + var eid string + select { + case <-initFailed: + t.FailNow() + case eid = <-eng.xxxExecutionFinished: + } + return eid +} + type mockCapability struct { capabilities.CapabilityInfo capabilities.CallbackExecutable @@ -148,23 +186,13 @@ func TestEngineWithHardcodedWorkflow(t *testing.T) { ) require.NoError(t, reg.Add(ctx, target2)) - lggr := logger.TestLogger(t) - peerID := p2ptypes.PeerID{} - cfg := Config{ - Lggr: lggr, - Registry: reg, - Spec: hardcodedWorkflow, - DONInfo: nil, - PeerID: func() *p2ptypes.PeerID { return &peerID }, - } - eng, err := NewEngine(cfg) - require.NoError(t, err) + eng, initFailed := newTestEngine(t, reg, hardcodedWorkflow) - err = eng.Start(ctx) + err := eng.Start(ctx) require.NoError(t, err) defer eng.Close() - eid := <-eng.xxxExecutionFinished + eid := getExecutionId(t, eng, initFailed) assert.Equal(t, cr, <-target1.response) assert.Equal(t, cr, <-target2.response) @@ -312,22 +340,13 @@ func TestEngine_ErrorsTheWorkflowIfAStepErrors(t *testing.T) { require.NoError(t, reg.Add(ctx, mockFailingConsensus())) require.NoError(t, reg.Add(ctx, mockTarget())) - peerID := p2ptypes.PeerID{} - cfg := Config{ - Lggr: logger.TestLogger(t), - Registry: reg, - Spec: simpleWorkflow, - DONInfo: nil, - PeerID: func() *p2ptypes.PeerID { return &peerID }, - } - eng, err := NewEngine(cfg) - require.NoError(t, err) + eng, initFailed := newTestEngine(t, reg, simpleWorkflow) - err = eng.Start(ctx) + err := eng.Start(ctx) require.NoError(t, err) defer eng.Close() - eid := <-eng.xxxExecutionFinished + eid := getExecutionId(t, eng, initFailed) state, err := eng.executionStates.get(ctx, eid) require.NoError(t, err) @@ -420,22 +439,12 @@ func TestEngine_MultiStepDependencies(t *testing.T) { action, out := mockAction() require.NoError(t, reg.Add(ctx, action)) - peerID := p2ptypes.PeerID{} - cfg := Config{ - Lggr: logger.TestLogger(t), - Registry: reg, - Spec: multiStepWorkflow, - DONInfo: nil, - PeerID: func() *p2ptypes.PeerID { return &peerID }, - } - eng, err := NewEngine(cfg) - require.NoError(t, err) - - err = eng.Start(ctx) + eng, initFailed := newTestEngine(t, reg, multiStepWorkflow) + err := eng.Start(ctx) require.NoError(t, err) defer eng.Close() - eid := <-eng.xxxExecutionFinished + eid := getExecutionId(t, eng, initFailed) state, err := eng.executionStates.get(ctx, eid) require.NoError(t, err) diff --git a/core/services/workflows/retry.go b/core/services/workflows/retry.go new file mode 100644 index 00000000000..e3f04353e7f --- /dev/null +++ b/core/services/workflows/retry.go @@ -0,0 +1,53 @@ +package workflows + +import ( + "context" + "fmt" + "time" + + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +// retryable is a helper function that retries a function until it succeeds. +// +// It will retry every `retryMs` milliseconds, up to `maxRetries` times. +// +// If `maxRetries` is 0, it will retry indefinitely. +// +// retryable will return an error in the following conditions: +// - the context is cancelled: the error returned is the context error +// - the retry limit has been hit: the error returned is the last error returned by `fn` +func retryable(ctx context.Context, lggr logger.Logger, retryMs int, maxRetries int, fn func() error) error { + ticker := time.NewTicker(time.Duration(retryMs) * time.Millisecond) + defer ticker.Stop() + + // immediately try once + err := fn() + if err == nil { + return nil + } + retries := 0 + + for { + // if maxRetries is 0, we'll retry indefinitely + if maxRetries > 0 { + if retries >= maxRetries { + lggr.Errorf("%s", err) + return fmt.Errorf("max retries reached, aborting") + } + } + lggr.Errorf("%s, retrying in %.2fs", err, float64(retryMs)/1000) + + select { + case <-ctx.Done(): + return ctx.Err() + case <-ticker.C: + err = fn() + if err == nil { + return nil + } + } + + retries++ + } +} diff --git a/core/services/workflows/retryable_test.go b/core/services/workflows/retryable_test.go new file mode 100644 index 00000000000..1a17ac55fae --- /dev/null +++ b/core/services/workflows/retryable_test.go @@ -0,0 +1,113 @@ +package workflows + +import ( + "context" + "errors" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestRetryableZeroMaxRetries(t *testing.T) { + t.Parallel() + + ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) + defer cancel() + + fn := func() error { + return errors.New("test error") + } + + err := retryable(ctx, logger.NullLogger, 100, 0, fn) + assert.ErrorIs(t, err, context.DeadlineExceeded, "Expected context deadline exceeded error") +} + +func TestRetryableSuccessOnFirstAttempt(t *testing.T) { + t.Parallel() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + fn := func() error { + return nil + } + + err := retryable(ctx, logger.NullLogger, 100, 3, fn) + require.NoError(t, err, "Expected no error as function succeeds on first attempt") +} + +func TestRetryableSuccessAfterRetries(t *testing.T) { + t.Parallel() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + retries := 0 + fn := func() error { + if retries < 2 { + retries++ + return errors.New("test error") + } + return nil + } + + err := retryable(ctx, logger.NullLogger, 100, 5, fn) + assert.NoError(t, err, "Expected no error after successful retry") + assert.Equal(t, 2, retries, "Expected two retries before success") +} + +func TestRetryableErrorOnFirstTryNoRetries(t *testing.T) { + t.Parallel() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + fn := func() error { + return errors.New("immediate failure") + } + + err := retryable(ctx, logger.NullLogger, 100, 1, fn) + require.Error(t, err, "Expected an error on the first try with no retries allowed") + assert.Equal(t, "max retries reached, aborting", err.Error(), "Expected function to abort after the first try") +} + +func TestRetryableErrorAfterMultipleRetries(t *testing.T) { + t.Parallel() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + attempts := 0 + fn := func() error { + attempts++ + return errors.New("persistent error") + } + + maxRetries := 3 + err := retryable(ctx, logger.NullLogger, 100, maxRetries, fn) + require.Error(t, err, "Expected an error after multiple retries") + assert.Equal(t, "max retries reached, aborting", err.Error(), "Expected the max retries reached error message") + assert.Equal(t, maxRetries+1, attempts, "Expected the function to be executed retry + 1 times") +} + +func TestRetryableCancellationHandling(t *testing.T) { + t.Parallel() + + ctx, cancel := context.WithCancel(context.Background()) + + fn := func() error { + return errors.New("test error") + } + + go func() { + time.Sleep(150 * time.Millisecond) + cancel() + }() + + err := retryable(ctx, logger.NullLogger, 100, 5, fn) + assert.ErrorIs(t, err, context.Canceled, "Expected context cancellation error") +} From 5872c452c7dace148431e49c6a8480171ea5d192 Mon Sep 17 00:00:00 2001 From: HenryNguyen5 <6404866+HenryNguyen5@users.noreply.github.com> Date: Mon, 29 Apr 2024 20:06:23 -0400 Subject: [PATCH 09/45] chore/fix incorrect flakey tests (#13021) * Add exit logs for go_core_tests * Print each iteration of a flakey test execution * DRY up env var usage to prevent typos * Remove .sh prefix on go_core_tests log Co-authored-by: Jordan Krage --------- Co-authored-by: Jordan Krage --- tools/bin/go_core_tests | 1 + tools/flakeytests/runner.go | 4 ++-- tools/flakeytests/runner_test.go | 23 +++++++++++++++++------ 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/tools/bin/go_core_tests b/tools/bin/go_core_tests index c0b0f43aed4..074527698b3 100755 --- a/tools/bin/go_core_tests +++ b/tools/bin/go_core_tests @@ -33,4 +33,5 @@ if [[ $EXITCODE != 0 ]]; then else echo "All tests passed!" fi +echo "go_core_tests exiting with code $EXITCODE" exit $EXITCODE diff --git a/tools/flakeytests/runner.go b/tools/flakeytests/runner.go index 88ab647e7c1..a37b123d5cf 100644 --- a/tools/flakeytests/runner.go +++ b/tools/flakeytests/runner.go @@ -219,8 +219,8 @@ func (r *Runner) runTests(rep *Report) (*Report, error) { ts = append(ts, test) } - log.Printf("[FLAKEY_TEST] Executing test command with parameters: pkg=%s, tests=%+v, numReruns=%d\n", pkg, ts, r.numReruns) for i := 0; i < r.numReruns; i++ { + log.Printf("[FLAKEY_TEST] Executing test command with parameters: pkg=%s, tests=%+v, numReruns=%d currentRun=%d\n", pkg, ts, r.numReruns, i) pr, err := r.runTest(pkg, ts) if err != nil { return report, err @@ -237,8 +237,8 @@ func (r *Runner) runTests(rep *Report) (*Report, error) { } for pkg := range rep.packagePanics { - log.Printf("[PACKAGE_PANIC]: Executing test command with parameters: pkg=%s, numReruns=%d\n", pkg, r.numReruns) for i := 0; i < r.numReruns; i++ { + log.Printf("[PACKAGE_PANIC]: Executing test command with parameters: pkg=%s, numReruns=%d currentRun=%d\n", pkg, r.numReruns, i) pr, err := r.runTest(pkg, []string{}) if err != nil { return report, err diff --git a/tools/flakeytests/runner_test.go b/tools/flakeytests/runner_test.go index ee069a1655d..8f9433a427b 100644 --- a/tools/flakeytests/runner_test.go +++ b/tools/flakeytests/runner_test.go @@ -14,6 +14,17 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" ) +// This test suite has two sets of tests that are run in two different modes: +// 1. Normal mode: The tests are run as usual. All tests that start with TestSkippedForTests will be skipped. +// There are a set of integration tests that will run this same test suite in integration mode. +// 2. Integration mode: The tests are run with an environment variable set to run the tests that were skipped in normal mode. +// Their output is captured and parsed to check if the flake runner is behaving as expected. +// +// In summary, the first set of tests are executed by the user, and these tests will trigger the second set of tests to run. +var runInIntegrationTestModeEnvKey = "FLAKEY_TEST_RUNNER_RUN_FIXTURE_TEST" +var skipIntegrationTestMode = os.Getenv(runInIntegrationTestModeEnvKey) != "1" +var runInIntegrationTestModeEnv = runInIntegrationTestModeEnvKey + "=1" + type mockReporter struct { report *Report } @@ -307,7 +318,7 @@ func TestRunner_RerunWithNonZeroExitCodeDoesntStopCommand(t *testing.T) { // Used for integration tests func TestSkippedForTests_Subtests(t *testing.T) { - if os.Getenv("FLAKEY_TEST_RUNNER_RUN_FIXTURE_TEST") != "1" { + if skipIntegrationTestMode { t.Skip() } @@ -322,7 +333,7 @@ func TestSkippedForTests_Subtests(t *testing.T) { // Used for integration tests func TestSkippedForTests(t *testing.T) { - if os.Getenv("FLAKEY_TEST_RUNNER_RUN_FIXTURE_TEST") != "1" { + if skipIntegrationTestMode { t.Skip() } @@ -333,7 +344,7 @@ func TestSkippedForTests(t *testing.T) { // Used for integration tests func TestSkippedForTests_Success(t *testing.T) { - if os.Getenv("FLAKEY_TEST_RUNNER_RUN_FIXTURE_TEST") != "1" { + if skipIntegrationTestMode { t.Skip() } @@ -356,7 +367,7 @@ func TestIntegration_DealsWithSubtests(t *testing.T) { repo: "github.com/smartcontractkit/chainlink/v2/tools/flakeytests", command: "../bin/go_core_tests", overrides: func(cmd *exec.Cmd) { - cmd.Env = append(cmd.Env, "FLAKEY_TESTRUNNER_RUN_FIXTURE_TEST=1") + cmd.Env = append(cmd.Env, runInIntegrationTestModeEnv) cmd.Stdout = io.Discard cmd.Stderr = io.Discard }, @@ -392,7 +403,7 @@ func TestIntegration_ParsesPanics(t *testing.T) { repo: "github.com/smartcontractkit/chainlink/v2/tools/flakeytests", command: "../bin/go_core_tests", overrides: func(cmd *exec.Cmd) { - cmd.Env = append(cmd.Env, "FLAKEY_TESTRUNNER_RUN_FIXTURE_TEST=1") + cmd.Env = append(cmd.Env, runInIntegrationTestModeEnv) cmd.Stdout = io.Discard cmd.Stderr = io.Discard }, @@ -423,7 +434,7 @@ func TestIntegration(t *testing.T) { repo: "github.com/smartcontractkit/chainlink/v2/tools/flakeytests", command: "../bin/go_core_tests", overrides: func(cmd *exec.Cmd) { - cmd.Env = append(cmd.Env, "FLAKEY_TESTRUNNER_RUN_FIXTURE_TEST=1") + cmd.Env = append(cmd.Env, runInIntegrationTestModeEnv) cmd.Stdout = io.Discard cmd.Stderr = io.Discard }, From f376a123dadd810e3efeb5b9a066b4615ff893ee Mon Sep 17 00:00:00 2001 From: HenryNguyen5 <6404866+HenryNguyen5@users.noreply.github.com> Date: Tue, 30 Apr 2024 00:04:58 -0400 Subject: [PATCH 10/45] Make sure short tests are actually passing (#12989) --- .github/workflows/ci-core.yml | 9 +++++++-- core/chains/evm/config/config_test.go | 2 ++ core/services/chainlink/config_database_test.go | 2 ++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml index 394faf71e2f..e1891770930 100644 --- a/.github/workflows/ci-core.yml +++ b/.github/workflows/ci-core.yml @@ -77,6 +77,10 @@ jobs: slack-message: "golangci-lint failed: ${{ job.html_url }}\n${{ format('https://github.com/smartcontractkit/chainlink/actions/runs/{0}', github.run_id) }}" core: + env: + # We explicitly have this env var not be "CL_DATABASE_URL" to avoid having it be used by core related tests + # when they should not be using it, while still allowing us to DRY up the setup + DB_URL: postgresql://postgres:postgres@localhost:5432/chainlink_test?sslmode=disable strategy: fail-fast: false matrix: @@ -92,8 +96,6 @@ jobs: if: github.actor != 'dependabot[bot]' needs: [filter] runs-on: ubuntu-latest-64cores-256GB - env: - CL_DATABASE_URL: postgresql://postgres:postgres@localhost:5432/chainlink_test?sslmode=disable steps: - name: Checkout the repo uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 @@ -136,6 +138,8 @@ jobs: - name: Setup DB if: ${{ needs.filter.outputs.changes == 'true' }} run: ./chainlink.test local db preparetest + env: + CL_DATABASE_URL: ${{ env.DB_URL }} - name: Install LOOP Plugins if: ${{ needs.filter.outputs.changes == 'true' }} run: | @@ -165,6 +169,7 @@ jobs: env: OUTPUT_FILE: ./output.txt USE_TEE: false + CL_DATABASE_URL: ${{ env.DB_URL }} run: ./tools/bin/${{ matrix.type.cmd }} ./... - name: Print Filtered Test Results if: ${{ failure() && matrix.type.cmd == 'go_core_tests' && needs.filter.outputs.changes == 'true' }} diff --git a/core/chains/evm/config/config_test.go b/core/chains/evm/config/config_test.go index e1c7a9f48cc..9553f59ad61 100644 --- a/core/chains/evm/config/config_test.go +++ b/core/chains/evm/config/config_test.go @@ -23,6 +23,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/store/models" ) func TestChainScopedConfig(t *testing.T) { @@ -380,6 +381,7 @@ func TestChainScopedConfig_HeadTracker(t *testing.T) { func Test_chainScopedConfig_Validate(t *testing.T) { configWithChains := func(t *testing.T, id int64, chains ...*toml.Chain) config.AppConfig { return configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { + s.Database.URL = models.MustSecretURL("postgresql://doesnotexist:justtopassvalidationtests@localhost:5432/chainlink_na_test") chainID := ubig.NewI(id) c.EVM[0] = &toml.EVMConfig{ChainID: chainID, Enabled: ptr(true), Chain: toml.Defaults(chainID, chains...), Nodes: toml.EVMNodes{{ diff --git a/core/services/chainlink/config_database_test.go b/core/services/chainlink/config_database_test.go index 9cde07c9a63..b52d17452aa 100644 --- a/core/services/chainlink/config_database_test.go +++ b/core/services/chainlink/config_database_test.go @@ -14,6 +14,8 @@ import ( func TestDatabaseConfig(t *testing.T) { opts := GeneralConfigOpts{ ConfigStrings: []string{fullTOML}, + SecretsStrings: []string{`[Database] +URL = "postgresql://doesnotexist:justtopassvalidationtests@localhost:5432/chainlink_na_test"`}, } cfg, err := opts.New() require.NoError(t, err) From d50936ce3824d7ad6026f630172e9764a34cc08b Mon Sep 17 00:00:00 2001 From: Mateusz Sekara Date: Tue, 30 Apr 2024 09:15:37 +0200 Subject: [PATCH 11/45] Added support for retention in the contract_transmitter.go (#12998) --- .changeset/witty-numbers-sleep.md | 5 +++++ .../relay/evm/contract_transmitter.go | 19 ++++++++++++++++++- core/services/relay/evm/evm.go | 10 ++++++---- core/services/relay/evm/ocr2keeper.go | 2 +- core/services/relay/evm/ocr2vrf.go | 4 ++-- 5 files changed, 32 insertions(+), 8 deletions(-) create mode 100644 .changeset/witty-numbers-sleep.md diff --git a/.changeset/witty-numbers-sleep.md b/.changeset/witty-numbers-sleep.md new file mode 100644 index 00000000000..d42664d9f76 --- /dev/null +++ b/.changeset/witty-numbers-sleep.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Support for retention in LogPoller's filters registered by ContractTransmitter #changed diff --git a/core/services/relay/evm/contract_transmitter.go b/core/services/relay/evm/contract_transmitter.go index af0f83f6979..724bbbe4aa0 100644 --- a/core/services/relay/evm/contract_transmitter.go +++ b/core/services/relay/evm/contract_transmitter.go @@ -5,6 +5,7 @@ import ( "database/sql" "encoding/hex" "math/big" + "time" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" @@ -63,13 +64,29 @@ func NewOCRContractTransmitter( lp logpoller.LogPoller, lggr logger.Logger, reportToEvmTxMeta ReportToEthMetadata, +) (*contractTransmitter, error) { + return NewOCRContractTransmitterWithRetention(ctx, address, caller, contractABI, transmitter, lp, lggr, reportToEvmTxMeta, 0) +} + +func NewOCRContractTransmitterWithRetention( + ctx context.Context, + address gethcommon.Address, + caller contractReader, + contractABI abi.ABI, + transmitter Transmitter, + lp logpoller.LogPoller, + lggr logger.Logger, + reportToEvmTxMeta ReportToEthMetadata, + retention time.Duration, ) (*contractTransmitter, error) { transmitted, ok := contractABI.Events["Transmitted"] if !ok { return nil, errors.New("invalid ABI, missing transmitted") } - err := lp.RegisterFilter(ctx, logpoller.Filter{Name: transmitterFilterName(address), EventSigs: []common.Hash{transmitted.ID}, Addresses: []common.Address{address}}) + // TODO It would be better to keep MaxLogsKept = 1 for the OCR contract transmitter instead of Retention. We are always interested only in the latest log. + // Although MaxLogsKept is present in the Filter struct, it is not supported by LogPoller yet. + err := lp.RegisterFilter(ctx, logpoller.Filter{Name: transmitterFilterName(address), EventSigs: []common.Hash{transmitted.ID}, Addresses: []common.Address{address}, Retention: retention}) if err != nil { return nil, err } diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go index 737a8e7561e..585d20df3ab 100644 --- a/core/services/relay/evm/evm.go +++ b/core/services/relay/evm/evm.go @@ -7,6 +7,7 @@ import ( "fmt" "strings" "sync" + "time" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" @@ -172,7 +173,7 @@ func (r *Relayer) NewPluginProvider(rargs commontypes.RelayArgs, pargs commontyp return nil, err } - transmitter, err := newOnChainContractTransmitter(ctx, r.lggr, rargs, pargs.TransmitterID, r.ks.Eth(), configWatcher, configTransmitterOpts{}, OCR2AggregatorTransmissionContractABI) + transmitter, err := newOnChainContractTransmitter(ctx, r.lggr, rargs, pargs.TransmitterID, r.ks.Eth(), configWatcher, configTransmitterOpts{}, OCR2AggregatorTransmissionContractABI, 0) if err != nil { return nil, err } @@ -476,7 +477,7 @@ type configTransmitterOpts struct { } // newOnChainContractTransmitter creates a new contract transmitter. -func newOnChainContractTransmitter(ctx context.Context, lggr logger.Logger, rargs commontypes.RelayArgs, transmitterID string, ethKeystore keystore.Eth, configWatcher *configWatcher, opts configTransmitterOpts, transmissionContractABI abi.ABI) (*contractTransmitter, error) { +func newOnChainContractTransmitter(ctx context.Context, lggr logger.Logger, rargs commontypes.RelayArgs, transmitterID string, ethKeystore keystore.Eth, configWatcher *configWatcher, opts configTransmitterOpts, transmissionContractABI abi.ABI, transmissionContractRetention time.Duration) (*contractTransmitter, error) { var relayConfig types.RelayConfig if err := json.Unmarshal(rargs.RelayConfig, &relayConfig); err != nil { return nil, err @@ -540,7 +541,7 @@ func newOnChainContractTransmitter(ctx context.Context, lggr logger.Logger, rarg return nil, pkgerrors.Wrap(err, "failed to create transmitter") } - return NewOCRContractTransmitter( + return NewOCRContractTransmitterWithRetention( ctx, configWatcher.contractAddress, configWatcher.chain.Client(), @@ -549,6 +550,7 @@ func newOnChainContractTransmitter(ctx context.Context, lggr logger.Logger, rarg configWatcher.chain.LogPoller(), lggr, nil, + transmissionContractRetention, ) } @@ -578,7 +580,7 @@ func (r *Relayer) NewMedianProvider(rargs commontypes.RelayArgs, pargs commontyp reportCodec := evmreportcodec.ReportCodec{} - contractTransmitter, err := newOnChainContractTransmitter(ctx, lggr, rargs, pargs.TransmitterID, r.ks.Eth(), configWatcher, configTransmitterOpts{}, OCR2AggregatorTransmissionContractABI) + contractTransmitter, err := newOnChainContractTransmitter(ctx, lggr, rargs, pargs.TransmitterID, r.ks.Eth(), configWatcher, configTransmitterOpts{}, OCR2AggregatorTransmissionContractABI, 0) if err != nil { return nil, err } diff --git a/core/services/relay/evm/ocr2keeper.go b/core/services/relay/evm/ocr2keeper.go index 78f4b43b43f..a839ce8430e 100644 --- a/core/services/relay/evm/ocr2keeper.go +++ b/core/services/relay/evm/ocr2keeper.go @@ -91,7 +91,7 @@ func (r *ocr2keeperRelayer) NewOCR2KeeperProvider(rargs commontypes.RelayArgs, p } gasLimit := cfgWatcher.chain.Config().EVM().OCR2().Automation().GasLimit() - contractTransmitter, err := newOnChainContractTransmitter(ctx, r.lggr, rargs, pargs.TransmitterID, r.ethKeystore, cfgWatcher, configTransmitterOpts{pluginGasLimit: &gasLimit}, OCR2AggregatorTransmissionContractABI) + contractTransmitter, err := newOnChainContractTransmitter(ctx, r.lggr, rargs, pargs.TransmitterID, r.ethKeystore, cfgWatcher, configTransmitterOpts{pluginGasLimit: &gasLimit}, OCR2AggregatorTransmissionContractABI, 0) if err != nil { return nil, err } diff --git a/core/services/relay/evm/ocr2vrf.go b/core/services/relay/evm/ocr2vrf.go index a108151be47..b83ce0fd81e 100644 --- a/core/services/relay/evm/ocr2vrf.go +++ b/core/services/relay/evm/ocr2vrf.go @@ -64,7 +64,7 @@ func (r *ocr2vrfRelayer) NewDKGProvider(rargs commontypes.RelayArgs, pargs commo if err != nil { return nil, err } - contractTransmitter, err := newOnChainContractTransmitter(ctx, r.lggr, rargs, pargs.TransmitterID, r.ethKeystore, configWatcher, configTransmitterOpts{}, OCR2AggregatorTransmissionContractABI) + contractTransmitter, err := newOnChainContractTransmitter(ctx, r.lggr, rargs, pargs.TransmitterID, r.ethKeystore, configWatcher, configTransmitterOpts{}, OCR2AggregatorTransmissionContractABI, 0) if err != nil { return nil, err } @@ -91,7 +91,7 @@ func (r *ocr2vrfRelayer) NewOCR2VRFProvider(rargs commontypes.RelayArgs, pargs c if err != nil { return nil, err } - contractTransmitter, err := newOnChainContractTransmitter(ctx, r.lggr, rargs, pargs.TransmitterID, r.ethKeystore, configWatcher, configTransmitterOpts{}, OCR2AggregatorTransmissionContractABI) + contractTransmitter, err := newOnChainContractTransmitter(ctx, r.lggr, rargs, pargs.TransmitterID, r.ethKeystore, configWatcher, configTransmitterOpts{}, OCR2AggregatorTransmissionContractABI, 0) if err != nil { return nil, err } From e21be2a890a50bd3cbac60c450e3c2d68ddefbd3 Mon Sep 17 00:00:00 2001 From: Mateusz Sekara Date: Tue, 30 Apr 2024 09:49:36 +0200 Subject: [PATCH 12/45] CCIP-2207 Boosting LogPoller performance by fixing how order by clauses are written (#13026) * Boosting LogPoller performance by fixing how order by clauses are written * Boosting LogPoller performance by fixing how order by clauses are written --- .changeset/proud-toys-travel.md | 5 +++++ core/chains/evm/logpoller/orm.go | 33 +++++++++++++++++--------------- 2 files changed, 23 insertions(+), 15 deletions(-) create mode 100644 .changeset/proud-toys-travel.md diff --git a/.changeset/proud-toys-travel.md b/.changeset/proud-toys-travel.md new file mode 100644 index 00000000000..e2b1f0c7269 --- /dev/null +++ b/.changeset/proud-toys-travel.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Improving LogPoller read queries by properly sorting by multiple columns #updated diff --git a/core/chains/evm/logpoller/orm.go b/core/chains/evm/logpoller/orm.go index 5e0a74a9183..d065553886e 100644 --- a/core/chains/evm/logpoller/orm.go +++ b/core/chains/evm/logpoller/orm.go @@ -224,7 +224,9 @@ func (o *DSORM) SelectLatestLogByEventSigWithConfs(ctx context.Context, eventSig AND event_sig = :event_sig AND address = :address AND block_number <= %s - ORDER BY (block_number, log_index) DESC LIMIT 1`, nestedBlockNumberQuery(confs)) + ORDER BY block_number desc, log_index DESC + LIMIT 1 + `, nestedBlockNumberQuery(confs)) var l Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -425,7 +427,7 @@ func (o *DSORM) SelectLogsByBlockRange(ctx context.Context, start, end int64) ([ WHERE evm_chain_id = :evm_chain_id AND block_number >= :start_block AND block_number <= :end_block - ORDER BY (block_number, log_index)` + ORDER BY block_number, log_index` var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -456,7 +458,7 @@ func (o *DSORM) SelectLogs(ctx context.Context, start, end int64, address common AND event_sig = :event_sig AND block_number >= :start_block AND block_number <= :end_block - ORDER BY (block_number, log_index)` + ORDER BY block_number, log_index` var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -488,7 +490,7 @@ func (o *DSORM) SelectLogsCreatedAfter(ctx context.Context, address common.Addre AND event_sig = :event_sig AND block_timestamp > :block_timestamp_after AND block_number <= %s - ORDER BY (block_number, log_index)`, nestedBlockNumberQuery(confs)) + ORDER BY block_number, log_index`, nestedBlockNumberQuery(confs)) var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -520,7 +522,7 @@ func (o *DSORM) SelectLogsWithSigs(ctx context.Context, start, end int64, addres AND address = :address AND event_sig = ANY(:event_sig_array) AND block_number BETWEEN :start_block AND :end_block - ORDER BY (block_number, log_index)` + ORDER BY block_number, log_index` query, sqlArgs, err := o.ds.BindNamed(query, args) if err != nil { @@ -647,7 +649,7 @@ func (o *DSORM) SelectLogsDataWordRange(ctx context.Context, address common.Addr AND substring(data from 32*:word_index+1 for 32) >= :word_value_min AND substring(data from 32*:word_index+1 for 32) <= :word_value_max AND block_number <= %s - ORDER BY (block_number, log_index)`, nestedBlockNumberQuery(confs)) + ORDER BY block_number, log_index`, nestedBlockNumberQuery(confs)) var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -678,7 +680,7 @@ func (o *DSORM) SelectLogsDataWordGreaterThan(ctx context.Context, address commo AND event_sig = :event_sig AND substring(data from 32*:word_index+1 for 32) >= :word_value_min AND block_number <= %s - ORDER BY (block_number, log_index)`, nestedBlockNumberQuery(confs)) + ORDER BY block_number, log_index`, nestedBlockNumberQuery(confs)) var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -710,7 +712,7 @@ func (o *DSORM) SelectLogsDataWordBetween(ctx context.Context, address common.Ad AND substring(data from 32*:word_index_min+1 for 32) <= :word_value AND substring(data from 32*:word_index_max+1 for 32) >= :word_value AND block_number <= %s - ORDER BY (block_number, log_index)`, nestedBlockNumberQuery(confs)) + ORDER BY block_number, log_index`, nestedBlockNumberQuery(confs)) var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -741,7 +743,7 @@ func (o *DSORM) SelectIndexedLogsTopicGreaterThan(ctx context.Context, address c AND event_sig = :event_sig AND topics[:topic_index] >= :topic_value_min AND block_number <= %s - ORDER BY (block_number, log_index)`, nestedBlockNumberQuery(confs)) + ORDER BY block_number, log_index`, nestedBlockNumberQuery(confs)) var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -774,7 +776,7 @@ func (o *DSORM) SelectIndexedLogsTopicRange(ctx context.Context, address common. AND topics[:topic_index] >= :topic_value_min AND topics[:topic_index] <= :topic_value_max AND block_number <= %s - ORDER BY (evm.logs.block_number, evm.logs.log_index)`, nestedBlockNumberQuery(confs)) + ORDER BY block_number, log_index`, nestedBlockNumberQuery(confs)) var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -805,7 +807,7 @@ func (o *DSORM) SelectIndexedLogs(ctx context.Context, address common.Address, e AND event_sig = :event_sig AND topics[:topic_index] = ANY(:topic_values) AND block_number <= %s - ORDER BY (block_number, log_index)`, nestedBlockNumberQuery(confs)) + ORDER BY block_number, log_index`, nestedBlockNumberQuery(confs)) var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -838,7 +840,7 @@ func (o *DSORM) SelectIndexedLogsByBlockRange(ctx context.Context, start, end in AND topics[:topic_index] = ANY(:topic_values) AND block_number >= :start_block AND block_number <= :end_block - ORDER BY (block_number, log_index)` + ORDER BY block_number, log_index` var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -872,7 +874,8 @@ func (o *DSORM) SelectIndexedLogsCreatedAfter(ctx context.Context, address commo AND topics[:topic_index] = ANY(:topic_values) AND block_timestamp > :block_timestamp_after AND block_number <= %s - ORDER BY (block_number, log_index)`, nestedBlockNumberQuery(confs)) + ORDER BY block_number, log_index + `, nestedBlockNumberQuery(confs)) var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -901,7 +904,7 @@ func (o *DSORM) SelectIndexedLogsByTxHash(ctx context.Context, address common.Ad AND address = :address AND event_sig = :event_sig AND tx_hash = :tx_hash - ORDER BY (block_number, log_index)` + ORDER BY block_number, log_index` var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) @@ -949,7 +952,7 @@ func (o *DSORM) SelectIndexedLogsWithSigsExcluding(ctx context.Context, sigA, si AND b.event_sig = :sigB AND b.block_number BETWEEN :start_block AND :end_block AND b.block_number <= %s - ORDER BY block_number,log_index ASC`, nestedQuery, nestedQuery) + ORDER BY block_number, log_index`, nestedQuery, nestedQuery) var logs []Log query, sqlArgs, err := o.ds.BindNamed(query, args) From 04b42f1dd7db449e5267e2491a9ba6971f41b1bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deividas=20Kar=C5=BEinauskas?= Date: Tue, 30 Apr 2024 12:41:07 +0300 Subject: [PATCH 13/45] Add getCapabilities to the CapabilityRegistry (#13031) * Add getCapabilities * Fix comments --- .changeset/early-cats-check.md | 5 ++ contracts/.changeset/bright-dingos-attend.md | 5 ++ .../src/v0.8/keystone/CapabilityRegistry.sol | 16 ++++++ .../src/v0.8/keystone/test/BaseTest.t.sol | 16 ++++++ ...CapabilityRegistry_AddCapabilityTest.t.sol | 54 +++++++------------ .../CapabilityRegistry_GetCapabilityIds.t.sol | 29 ++++++++++ .../src/v0.8/keystone/test/Constants.t.sol | 2 - .../mocks/CapabilityConfigurationContract.sol | 4 ++ .../keystone_capability_registry.go | 28 +++++++++- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 10 files changed, 121 insertions(+), 40 deletions(-) create mode 100644 .changeset/early-cats-check.md create mode 100644 contracts/.changeset/bright-dingos-attend.md create mode 100644 contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilityIds.t.sol diff --git a/.changeset/early-cats-check.md b/.changeset/early-cats-check.md new file mode 100644 index 00000000000..0408383bd03 --- /dev/null +++ b/.changeset/early-cats-check.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal diff --git a/contracts/.changeset/bright-dingos-attend.md b/contracts/.changeset/bright-dingos-attend.md new file mode 100644 index 00000000000..9d376e40c05 --- /dev/null +++ b/contracts/.changeset/bright-dingos-attend.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +#internal diff --git a/contracts/src/v0.8/keystone/CapabilityRegistry.sol b/contracts/src/v0.8/keystone/CapabilityRegistry.sol index ddf1d9b5635..540bbed9bab 100644 --- a/contracts/src/v0.8/keystone/CapabilityRegistry.sol +++ b/contracts/src/v0.8/keystone/CapabilityRegistry.sol @@ -193,6 +193,22 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { return s_capabilities[capabilityID]; } + /// @notice Returns all capabilities. This operation will copy capabilities + /// to memory, which can be quite expensive. This is designed to mostly be + /// used by view accessors that are queried without any gas fees. + /// @return Capability[] An array of capabilities + function getCapabilities() external view returns (Capability[] memory) { + bytes32[] memory capabilityIds = s_capabilityIds.values(); + Capability[] memory capabilities = new Capability[](capabilityIds.length); + + for (uint256 i; i < capabilityIds.length; ++i) { + bytes32 capabilityId = capabilityIds[i]; + capabilities[i] = getCapability(capabilityId); + } + + return capabilities; + } + /// @notice This functions returns a Capability ID packed into a bytes32 for cheaper access /// @return bytes32 A unique identifier for the capability function getCapabilityID(bytes32 capabilityType, bytes32 version) public pure returns (bytes32) { diff --git a/contracts/src/v0.8/keystone/test/BaseTest.t.sol b/contracts/src/v0.8/keystone/test/BaseTest.t.sol index 4517a256b15..a2b1b3a53eb 100644 --- a/contracts/src/v0.8/keystone/test/BaseTest.t.sol +++ b/contracts/src/v0.8/keystone/test/BaseTest.t.sol @@ -9,11 +9,27 @@ import {CapabilityRegistry} from "../CapabilityRegistry.sol"; contract BaseTest is Test, Constants { CapabilityRegistry internal s_capabilityRegistry; CapabilityConfigurationContract internal s_capabilityConfigurationContract; + CapabilityRegistry.Capability internal s_basicCapability; + CapabilityRegistry.Capability internal s_capabilityWithConfigurationContract; function setUp() public virtual { vm.startPrank(ADMIN); s_capabilityRegistry = new CapabilityRegistry(); s_capabilityConfigurationContract = new CapabilityConfigurationContract(); + + s_basicCapability = CapabilityRegistry.Capability({ + capabilityType: "data-streams-reports", + version: "1.0.0", + responseType: CapabilityRegistry.CapabilityResponseType.REPORT, + configurationContract: address(0) + }); + + s_capabilityWithConfigurationContract = CapabilityRegistry.Capability({ + capabilityType: "read-ethereum-mainnet-gas-price", + version: "1.0.2", + responseType: CapabilityRegistry.CapabilityResponseType.OBSERVATION_IDENTICAL, + configurationContract: address(s_capabilityConfigurationContract) + }); } function _getNodeOperators() internal view returns (CapabilityRegistry.NodeOperator[] memory) { diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol index d9e4b6b8383..cf1bc6c8d73 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol @@ -7,41 +7,25 @@ import {CapabilityConfigurationContract} from "./mocks/CapabilityConfigurationCo import {CapabilityRegistry} from "../CapabilityRegistry.sol"; contract CapabilityRegistry_AddCapabilityTest is BaseTest { - CapabilityRegistry.Capability private basicCapability = - CapabilityRegistry.Capability({ - capabilityType: "data-streams-reports", - version: "1.0.0", - responseType: CapabilityRegistry.CapabilityResponseType.REPORT, - configurationContract: address(0) - }); - - CapabilityRegistry.Capability private capabilityWithConfigurationContract = - CapabilityRegistry.Capability({ - capabilityType: "read-ethereum-mainnet-gas-price", - version: "1.0.2", - responseType: CapabilityRegistry.CapabilityResponseType.OBSERVATION_IDENTICAL, - configurationContract: address(s_capabilityConfigurationContract) - }); - function test_RevertWhen_CalledByNonAdmin() public { changePrank(STRANGER); vm.expectRevert("Only callable by owner"); - s_capabilityRegistry.addCapability(basicCapability); + s_capabilityRegistry.addCapability(s_basicCapability); } function test_RevertWhen_CapabilityExists() public { // Successfully add the capability the first time - s_capabilityRegistry.addCapability(basicCapability); + s_capabilityRegistry.addCapability(s_basicCapability); // Try to add the same capability again vm.expectRevert(CapabilityRegistry.CapabilityAlreadyExists.selector); - s_capabilityRegistry.addCapability(basicCapability); + s_capabilityRegistry.addCapability(s_basicCapability); } function test_RevertWhen_ConfigurationContractNotDeployed() public { address nonExistentContract = address(1); - capabilityWithConfigurationContract.configurationContract = nonExistentContract; + s_capabilityWithConfigurationContract.configurationContract = nonExistentContract; vm.expectRevert( abi.encodeWithSelector( @@ -49,41 +33,41 @@ contract CapabilityRegistry_AddCapabilityTest is BaseTest { nonExistentContract ) ); - s_capabilityRegistry.addCapability(capabilityWithConfigurationContract); + s_capabilityRegistry.addCapability(s_capabilityWithConfigurationContract); } function test_RevertWhen_ConfigurationContractDoesNotMatchInterface() public { CapabilityRegistry contractWithoutERC165 = new CapabilityRegistry(); vm.expectRevert(); - capabilityWithConfigurationContract.configurationContract = address(contractWithoutERC165); - s_capabilityRegistry.addCapability(capabilityWithConfigurationContract); + s_capabilityWithConfigurationContract.configurationContract = address(contractWithoutERC165); + s_capabilityRegistry.addCapability(s_capabilityWithConfigurationContract); } function test_AddCapability_NoConfigurationContract() public { - s_capabilityRegistry.addCapability(basicCapability); + s_capabilityRegistry.addCapability(s_basicCapability); bytes32 capabilityId = s_capabilityRegistry.getCapabilityID(bytes32("data-streams-reports"), bytes32("1.0.0")); CapabilityRegistry.Capability memory storedCapability = s_capabilityRegistry.getCapability(capabilityId); - assertEq(storedCapability.capabilityType, basicCapability.capabilityType); - assertEq(storedCapability.version, basicCapability.version); - assertEq(uint256(storedCapability.responseType), uint256(basicCapability.responseType)); - assertEq(storedCapability.configurationContract, basicCapability.configurationContract); + assertEq(storedCapability.capabilityType, s_basicCapability.capabilityType); + assertEq(storedCapability.version, s_basicCapability.version); + assertEq(uint256(storedCapability.responseType), uint256(s_basicCapability.responseType)); + assertEq(storedCapability.configurationContract, s_basicCapability.configurationContract); } function test_AddCapability_WithConfiguration() public { - s_capabilityRegistry.addCapability(capabilityWithConfigurationContract); + s_capabilityRegistry.addCapability(s_capabilityWithConfigurationContract); bytes32 capabilityId = s_capabilityRegistry.getCapabilityID( - bytes32(capabilityWithConfigurationContract.capabilityType), - bytes32(capabilityWithConfigurationContract.version) + bytes32(s_capabilityWithConfigurationContract.capabilityType), + bytes32(s_capabilityWithConfigurationContract.version) ); CapabilityRegistry.Capability memory storedCapability = s_capabilityRegistry.getCapability(capabilityId); - assertEq(storedCapability.capabilityType, capabilityWithConfigurationContract.capabilityType); - assertEq(storedCapability.version, capabilityWithConfigurationContract.version); - assertEq(uint256(storedCapability.responseType), uint256(capabilityWithConfigurationContract.responseType)); - assertEq(storedCapability.configurationContract, capabilityWithConfigurationContract.configurationContract); + assertEq(storedCapability.capabilityType, s_capabilityWithConfigurationContract.capabilityType); + assertEq(storedCapability.version, s_capabilityWithConfigurationContract.version); + assertEq(uint256(storedCapability.responseType), uint256(s_capabilityWithConfigurationContract.responseType)); + assertEq(storedCapability.configurationContract, s_capabilityWithConfigurationContract.configurationContract); } } diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilityIds.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilityIds.t.sol new file mode 100644 index 00000000000..de7810b4c15 --- /dev/null +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilityIds.t.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilityRegistry} from "../CapabilityRegistry.sol"; + +contract CapabilityRegistry_GetCapabilitiesTest is BaseTest { + function test_ReturnsCapabilities() public { + s_capabilityRegistry.addCapability(s_basicCapability); + s_capabilityRegistry.addCapability(s_capabilityWithConfigurationContract); + + CapabilityRegistry.Capability[] memory capabilities = s_capabilityRegistry.getCapabilities(); + + assertEq(capabilities.length, 2); + + assertEq(capabilities[0].capabilityType, "data-streams-reports"); + assertEq(capabilities[0].version, "1.0.0"); + assertEq(uint256(capabilities[0].responseType), uint256(CapabilityRegistry.CapabilityResponseType.REPORT)); + assertEq(capabilities[0].configurationContract, address(0)); + + assertEq(capabilities[1].capabilityType, "read-ethereum-mainnet-gas-price"); + assertEq(capabilities[1].version, "1.0.2"); + assertEq( + uint256(capabilities[1].responseType), + uint256(CapabilityRegistry.CapabilityResponseType.OBSERVATION_IDENTICAL) + ); + assertEq(capabilities[1].configurationContract, address(s_capabilityConfigurationContract)); + } +} diff --git a/contracts/src/v0.8/keystone/test/Constants.t.sol b/contracts/src/v0.8/keystone/test/Constants.t.sol index b7eb85debb1..6f0b7ef43f3 100644 --- a/contracts/src/v0.8/keystone/test/Constants.t.sol +++ b/contracts/src/v0.8/keystone/test/Constants.t.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; -import {Test} from "forge-std/Test.sol"; - contract Constants { address internal ADMIN = address(1); address internal STRANGER = address(2); diff --git a/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol b/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol index 0c3d8e0597d..6f3a28b7ca0 100644 --- a/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol +++ b/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol @@ -10,4 +10,8 @@ contract CapabilityConfigurationContract is ICapabilityConfiguration, ERC165 { function getCapabilityConfiguration(uint256 donId) external view returns (bytes memory configuration) { return s_donConfiguration[donId]; } + + function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { + return interfaceId == this.getCapabilityConfiguration.selector; + } } diff --git a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go index 61060bcb8ea..d1f789f4408 100644 --- a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go +++ b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go @@ -43,8 +43,8 @@ type CapabilityRegistryNodeOperator struct { } var CapabilityRegistryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"lengthOne\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lengthTwo\",\"type\":\"uint256\"}],\"name\":\"LengthMismatch\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityID\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"updateNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611702806101576000396000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c8063398f3773116100815780638da5cb5b1161005b5780638da5cb5b146101ad5780639cb7c5f4146101d5578063f2fde38b146101f557600080fd5b8063398f37731461017257806365c14dc71461018557806379ba5097146101a557600080fd5b8063181f5a77116100b2578063181f5a77146100f65780631cdf63431461013e578063229111f51461015157600080fd5b80630c5801e3146100ce578063117392ce146100e3575b600080fd5b6100e16100dc366004610efe565b610208565b005b6100e16100f1366004610f6a565b610519565b604080518082018252601881527f4361706162696c697479526567697374727920312e302e300000000000000000602082015290516101359190610fe6565b60405180910390f35b6100e161014c366004610ff9565b61074a565b61016461015f36600461103b565b61080d565b604051908152602001610135565b6100e1610180366004610ff9565b61083c565b61019861019336600461105d565b6109d5565b6040516101359190611076565b6100e1610abb565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610135565b6101e86101e336600461105d565b610bb8565b60405161013591906110e8565b6100e1610203366004611186565b610c62565b828114610250576040517fab8b67c600000000000000000000000000000000000000000000000000000000815260048101849052602481018290526044015b60405180910390fd5b6000805473ffffffffffffffffffffffffffffffffffffffff16905b84811015610511576000868683818110610288576102886111a3565b90506020020135905060008585848181106102a5576102a56111a3565b90506020028101906102b791906111d2565b6102c0906112b7565b805190915073ffffffffffffffffffffffffffffffffffffffff16610311576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16331480159061034e57503373ffffffffffffffffffffffffffffffffffffffff851614155b15610385576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160008381526005602052604090205473ffffffffffffffffffffffffffffffffffffffff908116911614158061043757506020808201516040516103cb9201610fe6565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012060008681526005835292909220919261041e9260010191016113d0565b6040516020818303038152906040528051906020012014155b156104fe578051600083815260056020908152604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921782558201516001909101906104a490826114bf565b50806000015173ffffffffffffffffffffffffffffffffffffffff167f14c8f513e8a6d86d2d16b0cb64976de4e72386c4f8068eca3b7354373f8fe97a8383602001516040516104f59291906115d9565b60405180910390a25b50508061050a906115f2565b905061026c565b505050505050565b610521610c76565b60006105328235602084013561080d565b905061053f600382610cf9565b15610576576040517fe288638f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105886080840160608501611186565b73ffffffffffffffffffffffffffffffffffffffff16146106f3576105b36080830160608401611186565b73ffffffffffffffffffffffffffffffffffffffff163b158061069357506105e16080830160608401611186565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f884efe6100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff91909116906301ffc9a790602401602060405180830381865afa15801561066d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106919190611651565b155b156106f3576106a86080830160608401611186565b6040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610247565b6106fe600382610d14565b50600081815260026020526040902082906107198282611673565b505060405181907f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff0690600090a25050565b610752610c76565b60005b81811015610808576000838383818110610771576107716111a3565b60209081029290920135600081815260059093526040832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559093509190506107c26001830182610e64565b50506040518181527f1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f9060200160405180910390a150610801816115f2565b9050610755565b505050565b604080516020808201859052818301849052825180830384018152606090920190925280519101205b92915050565b610844610c76565b60005b81811015610808576000838383818110610863576108636111a3565b905060200281019061087591906111d2565b61087e906112b7565b805190915073ffffffffffffffffffffffffffffffffffffffff166108cf576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600654604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526005909252939020825181547fffffffffffffffffffffffff00000000000000000000000000000000000000001692169190911781559151909190600182019061095290826114bf565b50905050600660008154610965906115f2565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b916109ba918591906115d9565b60405180910390a25050806109ce906115f2565b9050610847565b6040805180820190915260008152606060208201526000828152600560209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610a3290611383565b80601f0160208091040260200160405190810160405280929190818152602001828054610a5e90611383565b8015610aab5780601f10610a8057610100808354040283529160200191610aab565b820191906000526020600020905b815481529060010190602001808311610a8e57829003601f168201915b5050505050815250509050919050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610b3c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610247565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b604080516080808201835260008083526020808401829052838501829052606084018290528582526002808252918590208551938401865280548452600180820154928501929092529182015493949293919284019160ff1690811115610c2157610c216110b9565b6001811115610c3257610c326110b9565b815260029190910154610100900473ffffffffffffffffffffffffffffffffffffffff1660209091015292915050565b610c6a610c76565b610c7381610d20565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610cf7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610247565b565b600081815260018301602052604081205415155b9392505050565b6000610d0d8383610e15565b3373ffffffffffffffffffffffffffffffffffffffff821603610d9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610247565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000818152600183016020526040812054610e5c57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610836565b506000610836565b508054610e7090611383565b6000825580601f10610e80575050565b601f016020900490600052602060002090810190610c7391905b80821115610eae5760008155600101610e9a565b5090565b60008083601f840112610ec457600080fd5b50813567ffffffffffffffff811115610edc57600080fd5b6020830191508360208260051b8501011115610ef757600080fd5b9250929050565b60008060008060408587031215610f1457600080fd5b843567ffffffffffffffff80821115610f2c57600080fd5b610f3888838901610eb2565b90965094506020870135915080821115610f5157600080fd5b50610f5e87828801610eb2565b95989497509550505050565b600060808284031215610f7c57600080fd5b50919050565b6000815180845260005b81811015610fa857602081850181015186830182015201610f8c565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610d0d6020830184610f82565b6000806020838503121561100c57600080fd5b823567ffffffffffffffff81111561102357600080fd5b61102f85828601610eb2565b90969095509350505050565b6000806040838503121561104e57600080fd5b50508035926020909101359150565b60006020828403121561106f57600080fd5b5035919050565b6020815273ffffffffffffffffffffffffffffffffffffffff8251166020820152600060208301516040808401526110b16060840182610f82565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b81518152602080830151908201526040820151608082019060028110611137577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8060408401525073ffffffffffffffffffffffffffffffffffffffff606084015116606083015292915050565b73ffffffffffffffffffffffffffffffffffffffff81168114610c7357600080fd5b60006020828403121561119857600080fd5b8135610d0d81611164565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261120657600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561126257611262611210565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156112af576112af611210565b604052919050565b6000604082360312156112c957600080fd5b6112d161123f565b82356112dc81611164565b815260208381013567ffffffffffffffff808211156112fa57600080fd5b9085019036601f83011261130d57600080fd5b81358181111561131f5761131f611210565b61134f847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611268565b9150808252368482850101111561136557600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c9082168061139757607f821691505b602082108103610f7c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006020808352600084546113e481611383565b80848701526040600180841660008114611405576001811461143d5761146b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a0101955061146b565b896000528660002060005b858110156114635781548b8201860152908301908801611448565b8a0184019650505b509398975050505050505050565b601f82111561080857600081815260208120601f850160051c810160208610156114a05750805b601f850160051c820191505b81811015610511578281556001016114ac565b815167ffffffffffffffff8111156114d9576114d9611210565b6114ed816114e78454611383565b84611479565b602080601f831160018114611540576000841561150a5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610511565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561158d5788860151825594840194600190910190840161156e565b50858210156115c957878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8281526040602082015260006110b16040830184610f82565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361164a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b60006020828403121561166357600080fd5b81518015158114610d0d57600080fd5b81358155602082013560018201556002810160408301356002811061169757600080fd5b815460608501356116a781611164565b74ffffffffffffffffffffffffffffffffffffffff008160081b1660ff84167fffffffffffffffffffffff00000000000000000000000000000000000000000084161717845550505050505056fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"lengthOne\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lengthTwo\",\"type\":\"uint256\"}],\"name\":\"LengthMismatch\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilities\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityID\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"updateNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6118e3806101576000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c806365c14dc7116100815780639cb7c5f41161005b5780639cb7c5f4146101e0578063ddbe4f8214610200578063f2fde38b1461021557600080fd5b806365c14dc71461019057806379ba5097146101b05780638da5cb5b146101b857600080fd5b80631cdf6343116100b25780631cdf634314610149578063229111f51461015c578063398f37731461017d57600080fd5b80630c5801e3146100d9578063117392ce146100ee578063181f5a7714610101575b600080fd5b6100ec6100e736600461108f565b610228565b005b6100ec6100fc3660046110fb565b610539565b604080518082018252601881527f4361706162696c697479526567697374727920312e302e300000000000000000602082015290516101409190611177565b60405180910390f35b6100ec61015736600461118a565b61076a565b61016f61016a3660046111cc565b61082d565b604051908152602001610140565b6100ec61018b36600461118a565b61085c565b6101a361019e3660046111ee565b6109f5565b6040516101409190611207565b6100ec610adb565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610140565b6101f36101ee3660046111ee565b610bd8565b60405161014091906112e9565b610208610c82565b60405161014091906112f7565b6100ec610223366004611367565b610d8a565b828114610270576040517fab8b67c600000000000000000000000000000000000000000000000000000000815260048101849052602481018290526044015b60405180910390fd5b6000805473ffffffffffffffffffffffffffffffffffffffff16905b848110156105315760008686838181106102a8576102a8611384565b90506020020135905060008585848181106102c5576102c5611384565b90506020028101906102d791906113b3565b6102e090611498565b805190915073ffffffffffffffffffffffffffffffffffffffff16610331576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16331480159061036e57503373ffffffffffffffffffffffffffffffffffffffff851614155b156103a5576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160008381526005602052604090205473ffffffffffffffffffffffffffffffffffffffff908116911614158061045757506020808201516040516103eb9201611177565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012060008681526005835292909220919261043e9260010191016115b1565b6040516020818303038152906040528051906020012014155b1561051e578051600083815260056020908152604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921782558201516001909101906104c490826116a0565b50806000015173ffffffffffffffffffffffffffffffffffffffff167f14c8f513e8a6d86d2d16b0cb64976de4e72386c4f8068eca3b7354373f8fe97a8383602001516040516105159291906117ba565b60405180910390a25b50508061052a906117d3565b905061028c565b505050505050565b610541610d9e565b60006105528235602084013561082d565b905061055f600382610e21565b15610596576040517fe288638f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105a86080840160608501611367565b73ffffffffffffffffffffffffffffffffffffffff1614610713576105d36080830160608401611367565b73ffffffffffffffffffffffffffffffffffffffff163b15806106b357506106016080830160608401611367565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f884efe6100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff91909116906301ffc9a790602401602060405180830381865afa15801561068d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b19190611832565b155b15610713576106c86080830160608401611367565b6040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610267565b61071e600382610e3c565b50600081815260026020526040902082906107398282611854565b505060405181907f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff0690600090a25050565b610772610d9e565b60005b8181101561082857600083838381811061079157610791611384565b60209081029290920135600081815260059093526040832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559093509190506107e26001830182610ff5565b50506040518181527f1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f9060200160405180910390a150610821816117d3565b9050610775565b505050565b604080516020808201859052818301849052825180830384018152606090920190925280519101205b92915050565b610864610d9e565b60005b8181101561082857600083838381811061088357610883611384565b905060200281019061089591906113b3565b61089e90611498565b805190915073ffffffffffffffffffffffffffffffffffffffff166108ef576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600654604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526005909252939020825181547fffffffffffffffffffffffff00000000000000000000000000000000000000001692169190911781559151909190600182019061097290826116a0565b50905050600660008154610985906117d3565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b916109da918591906117ba565b60405180910390a25050806109ee906117d3565b9050610867565b6040805180820190915260008152606060208201526000828152600560209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610a5290611564565b80601f0160208091040260200160405190810160405280929190818152602001828054610a7e90611564565b8015610acb5780601f10610aa057610100808354040283529160200191610acb565b820191906000526020600020905b815481529060010190602001808311610aae57829003601f168201915b5050505050815250509050919050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610b5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610267565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b604080516080808201835260008083526020808401829052838501829052606084018290528582526002808252918590208551938401865280548452600180820154928501929092529182015493949293919284019160ff1690811115610c4157610c4161124a565b6001811115610c5257610c5261124a565b815260029190910154610100900473ffffffffffffffffffffffffffffffffffffffff1660209091015292915050565b60606000610c906003610e48565b90506000815167ffffffffffffffff811115610cae57610cae6113f1565b604051908082528060200260200182016040528015610d1e57816020015b6040805160808101825260008082526020808301829052928201819052606082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181610ccc5790505b50905060005b8251811015610d83576000838281518110610d4157610d41611384565b60200260200101519050610d5481610bd8565b838381518110610d6657610d66611384565b60200260200101819052505080610d7c906117d3565b9050610d24565b5092915050565b610d92610d9e565b610d9b81610e55565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610e1f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610267565b565b600081815260018301602052604081205415155b9392505050565b6000610e358383610f4a565b60606000610e3583610f99565b3373ffffffffffffffffffffffffffffffffffffffff821603610ed4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610267565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000818152600183016020526040812054610f9157508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610856565b506000610856565b606081600001805480602002602001604051908101604052809291908181526020018280548015610fe957602002820191906000526020600020905b815481526020019060010190808311610fd5575b50505050509050919050565b50805461100190611564565b6000825580601f10611011575050565b601f016020900490600052602060002090810190610d9b91905b8082111561103f576000815560010161102b565b5090565b60008083601f84011261105557600080fd5b50813567ffffffffffffffff81111561106d57600080fd5b6020830191508360208260051b850101111561108857600080fd5b9250929050565b600080600080604085870312156110a557600080fd5b843567ffffffffffffffff808211156110bd57600080fd5b6110c988838901611043565b909650945060208701359150808211156110e257600080fd5b506110ef87828801611043565b95989497509550505050565b60006080828403121561110d57600080fd5b50919050565b6000815180845260005b818110156111395760208185018101518683018201520161111d565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610e356020830184611113565b6000806020838503121561119d57600080fd5b823567ffffffffffffffff8111156111b457600080fd5b6111c085828601611043565b90969095509350505050565b600080604083850312156111df57600080fd5b50508035926020909101359150565b60006020828403121561120057600080fd5b5035919050565b6020815273ffffffffffffffffffffffffffffffffffffffff8251166020820152600060208301516040808401526112426060840182611113565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b80518252602081015160208301526040810151600281106112c3577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b604083015260609081015173ffffffffffffffffffffffffffffffffffffffff16910152565b608081016108568284611279565b6020808252825182820181905260009190848201906040850190845b8181101561133957611326838551611279565b9284019260809290920191600101611313565b50909695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610d9b57600080fd5b60006020828403121561137957600080fd5b8135610e3581611345565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126113e757600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611443576114436113f1565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611490576114906113f1565b604052919050565b6000604082360312156114aa57600080fd5b6114b2611420565b82356114bd81611345565b815260208381013567ffffffffffffffff808211156114db57600080fd5b9085019036601f8301126114ee57600080fd5b813581811115611500576115006113f1565b611530847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611449565b9150808252368482850101111561154657600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c9082168061157857607f821691505b60208210810361110d577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006020808352600084546115c581611564565b808487015260406001808416600081146115e6576001811461161e5761164c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a0101955061164c565b896000528660002060005b858110156116445781548b8201860152908301908801611629565b8a0184019650505b509398975050505050505050565b601f82111561082857600081815260208120601f850160051c810160208610156116815750805b601f850160051c820191505b818110156105315782815560010161168d565b815167ffffffffffffffff8111156116ba576116ba6113f1565b6116ce816116c88454611564565b8461165a565b602080601f83116001811461172157600084156116eb5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610531565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561176e5788860151825594840194600190910190840161174f565b50858210156117aa57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8281526040602082015260006112426040830184611113565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361182b577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b60006020828403121561184457600080fd5b81518015158114610e3557600080fd5b81358155602082013560018201556002810160408301356002811061187857600080fd5b8154606085013561188881611345565b74ffffffffffffffffffffffffffffffffffffffff008160081b1660ff84167fffffffffffffffffffffff00000000000000000000000000000000000000000084161717845550505050505056fea164736f6c6343000813000a", } var CapabilityRegistryABI = CapabilityRegistryMetaData.ABI @@ -183,6 +183,28 @@ func (_CapabilityRegistry *CapabilityRegistryTransactorRaw) Transact(opts *bind. return _CapabilityRegistry.Contract.contract.Transact(opts, method, params...) } +func (_CapabilityRegistry *CapabilityRegistryCaller) GetCapabilities(opts *bind.CallOpts) ([]CapabilityRegistryCapability, error) { + var out []interface{} + err := _CapabilityRegistry.contract.Call(opts, &out, "getCapabilities") + + if err != nil { + return *new([]CapabilityRegistryCapability), err + } + + out0 := *abi.ConvertType(out[0], new([]CapabilityRegistryCapability)).(*[]CapabilityRegistryCapability) + + return out0, err + +} + +func (_CapabilityRegistry *CapabilityRegistrySession) GetCapabilities() ([]CapabilityRegistryCapability, error) { + return _CapabilityRegistry.Contract.GetCapabilities(&_CapabilityRegistry.CallOpts) +} + +func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapabilities() ([]CapabilityRegistryCapability, error) { + return _CapabilityRegistry.Contract.GetCapabilities(&_CapabilityRegistry.CallOpts) +} + func (_CapabilityRegistry *CapabilityRegistryCaller) GetCapability(opts *bind.CallOpts, capabilityID [32]byte) (CapabilityRegistryCapability, error) { var out []interface{} err := _CapabilityRegistry.contract.Call(opts, &out, "getCapability", capabilityID) @@ -1188,6 +1210,8 @@ func (_CapabilityRegistry *CapabilityRegistry) Address() common.Address { } type CapabilityRegistryInterface interface { + GetCapabilities(opts *bind.CallOpts) ([]CapabilityRegistryCapability, error) + GetCapability(opts *bind.CallOpts, capabilityID [32]byte) (CapabilityRegistryCapability, error) GetCapabilityID(opts *bind.CallOpts, capabilityType [32]byte, version [32]byte) ([32]byte, error) diff --git a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt index e137d35ea5e..efe3e4eaf90 100644 --- a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,4 +1,4 @@ GETH_VERSION: 1.13.8 forwarder: ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.bin b4c900aae9e022f01abbac7993d41f93912247613ac6270b0c4da4ef6f2016e3 -keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin 5f801185084a6d6bcc08e0a37574d80f5092bc0dcd40808e9e04804064db0a56 +keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin ae9e077854854fa066746eaa354324c7dac2a13bc38b81a66c856fddfc3b79bf ocr3_capability: ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.bin 9dcbdf55bd5729ba266148da3f17733eb592c871c2108ccca546618628fd9ad2 From 77efb61e562fb456ac5bef3b6a528904cda000ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deividas=20Kar=C5=BEinauskas?= Date: Tue, 30 Apr 2024 14:49:29 +0300 Subject: [PATCH 14/45] Add deprecateCapability (#13036) * Add getCapabilities * Fix comments * Add deprecateCapability * Wrappers + changesets * Name fixes --- .changeset/beige-papayas-develop.md | 5 + contracts/.changeset/plenty-ligers-joke.md | 5 + .../src/v0.8/keystone/CapabilityRegistry.sol | 47 ++++- ...pabilityRegistry_DeprecateCapability.t.sol | 69 +++++++ .../CapabilityRegistry_GetCapabilities.t.sol | 52 +++++ .../keystone_capability_registry.go | 181 +++++++++++++++++- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 7 files changed, 356 insertions(+), 5 deletions(-) create mode 100644 .changeset/beige-papayas-develop.md create mode 100644 contracts/.changeset/plenty-ligers-joke.md create mode 100644 contracts/src/v0.8/keystone/test/CapabilityRegistry_DeprecateCapability.t.sol create mode 100644 contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilities.t.sol diff --git a/.changeset/beige-papayas-develop.md b/.changeset/beige-papayas-develop.md new file mode 100644 index 00000000000..0408383bd03 --- /dev/null +++ b/.changeset/beige-papayas-develop.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal diff --git a/contracts/.changeset/plenty-ligers-joke.md b/contracts/.changeset/plenty-ligers-joke.md new file mode 100644 index 00000000000..9d376e40c05 --- /dev/null +++ b/contracts/.changeset/plenty-ligers-joke.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +#internal diff --git a/contracts/src/v0.8/keystone/CapabilityRegistry.sol b/contracts/src/v0.8/keystone/CapabilityRegistry.sol index 540bbed9bab..9d627c2afb5 100644 --- a/contracts/src/v0.8/keystone/CapabilityRegistry.sol +++ b/contracts/src/v0.8/keystone/CapabilityRegistry.sol @@ -74,6 +74,16 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// exists. error CapabilityAlreadyExists(); + /// @notice This error is thrown when a capability with the provided ID is + /// not found. + /// @param capabilityId The ID used for the lookup. + error CapabilityDoesNotExist(bytes32 capabilityId); + + /// @notice This error is thrown when trying to deprecate a capability that + /// is already deprecated. + /// @param capabilityId The ID of the capability that is already deprecated. + error CapabilityAlreadyDeprecated(bytes32 capabilityId); + /// @notice This error is thrown when trying to add a capability with a /// configuration contract that does not implement the required interface. /// @param proposedConfigurationContract The address of the proposed @@ -101,8 +111,13 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @param capabilityId The ID of the newly added capability event CapabilityAdded(bytes32 indexed capabilityId); + /// @notice This event is emitted when a capability is deprecated + /// @param capabilityId The ID of the deprecated capability + event CapabilityDeprecated(bytes32 indexed capabilityId); + mapping(bytes32 => Capability) private s_capabilities; EnumerableSet.Bytes32Set private s_capabilityIds; + EnumerableSet.Bytes32Set private s_deprecatedCapabilityIds; /// @notice Mapping of node operators mapping(uint256 nodeOperatorId => NodeOperator) private s_nodeOperators; @@ -189,6 +204,16 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { emit CapabilityAdded(capabilityId); } + /// @notice Deprecates a capability by adding it to the deprecated list + /// @param capabilityId The ID of the capability to deprecate + function deprecateCapability(bytes32 capabilityId) external onlyOwner { + if (!s_capabilityIds.contains(capabilityId)) revert CapabilityDoesNotExist(capabilityId); + if (s_deprecatedCapabilityIds.contains(capabilityId)) revert CapabilityAlreadyDeprecated(capabilityId); + + s_deprecatedCapabilityIds.add(capabilityId); + emit CapabilityDeprecated(capabilityId); + } + function getCapability(bytes32 capabilityID) public view returns (Capability memory) { return s_capabilities[capabilityID]; } @@ -199,11 +224,22 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @return Capability[] An array of capabilities function getCapabilities() external view returns (Capability[] memory) { bytes32[] memory capabilityIds = s_capabilityIds.values(); - Capability[] memory capabilities = new Capability[](capabilityIds.length); + + // Solidity does not support dynamic arrays in memory, so we create a + // fixed-size array and copy the capabilities into it. + Capability[] memory capabilities = new Capability[](capabilityIds.length - s_deprecatedCapabilityIds.length()); + + // We need to keep track of the new index because we are skipping + // deprecated capabilities. + uint256 newIndex; for (uint256 i; i < capabilityIds.length; ++i) { bytes32 capabilityId = capabilityIds[i]; - capabilities[i] = getCapability(capabilityId); + + if (!s_deprecatedCapabilityIds.contains(capabilityId)) { + capabilities[newIndex] = getCapability(capabilityId); + newIndex++; + } } return capabilities; @@ -214,4 +250,11 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { function getCapabilityID(bytes32 capabilityType, bytes32 version) public pure returns (bytes32) { return keccak256(abi.encodePacked(capabilityType, version)); } + + /// @notice Returns whether a capability is deprecated + /// @param capabilityId The ID of the capability to check + /// @return bool True if the capability is deprecated, false otherwise + function isCapabilityDeprecated(bytes32 capabilityId) external view returns (bool) { + return s_deprecatedCapabilityIds.contains(capabilityId); + } } diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_DeprecateCapability.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_DeprecateCapability.t.sol new file mode 100644 index 00000000000..ceefdf431cf --- /dev/null +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_DeprecateCapability.t.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; + +import {CapabilityRegistry} from "../CapabilityRegistry.sol"; + +contract CapabilityRegistry_AddCapabilityTest is BaseTest { + event CapabilityDeprecated(bytes32 indexed capabilityId); + + function setUp() public override { + BaseTest.setUp(); + + s_capabilityRegistry.addCapability(s_basicCapability); + s_capabilityRegistry.addCapability(s_capabilityWithConfigurationContract); + } + + function test_RevertWhen_CalledByNonAdmin() public { + changePrank(STRANGER); + bytes32 capabilityId = s_capabilityRegistry.getCapabilityID( + s_basicCapability.capabilityType, + s_basicCapability.version + ); + + vm.expectRevert("Only callable by owner"); + s_capabilityRegistry.deprecateCapability(capabilityId); + } + + function test_RevertWhen_CapabilityDoesNotExist() public { + bytes32 capabilityId = s_capabilityRegistry.getCapabilityID("non-existent-capability", "1.0.0"); + + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.CapabilityDoesNotExist.selector, capabilityId)); + s_capabilityRegistry.deprecateCapability(capabilityId); + } + + function test_RevertWhen_CapabilityAlreadyDeprecated() public { + bytes32 capabilityId = s_capabilityRegistry.getCapabilityID( + s_basicCapability.capabilityType, + s_basicCapability.version + ); + + s_capabilityRegistry.deprecateCapability(capabilityId); + + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.CapabilityAlreadyDeprecated.selector, capabilityId)); + s_capabilityRegistry.deprecateCapability(capabilityId); + } + + function test_DeprecatesCapability() public { + bytes32 capabilityId = s_capabilityRegistry.getCapabilityID( + s_basicCapability.capabilityType, + s_basicCapability.version + ); + + s_capabilityRegistry.deprecateCapability(capabilityId); + + assertEq(s_capabilityRegistry.isCapabilityDeprecated(capabilityId), true); + } + + function test_EmitsEvent() public { + bytes32 capabilityId = s_capabilityRegistry.getCapabilityID( + s_basicCapability.capabilityType, + s_basicCapability.version + ); + + vm.expectEmit(address(s_capabilityRegistry)); + emit CapabilityDeprecated(capabilityId); + s_capabilityRegistry.deprecateCapability(capabilityId); + } +} diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilities.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilities.t.sol new file mode 100644 index 00000000000..b14397ba4ef --- /dev/null +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilities.t.sol @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilityRegistry} from "../CapabilityRegistry.sol"; + +contract CapabilityRegistry_GetCapabilitiesTest is BaseTest { + function setUp() public override { + BaseTest.setUp(); + + s_capabilityRegistry.addCapability(s_basicCapability); + s_capabilityRegistry.addCapability(s_capabilityWithConfigurationContract); + } + + function test_ReturnsCapabilities() public view { + CapabilityRegistry.Capability[] memory capabilities = s_capabilityRegistry.getCapabilities(); + + assertEq(capabilities.length, 2); + + assertEq(capabilities[0].capabilityType, "data-streams-reports"); + assertEq(capabilities[0].version, "1.0.0"); + assertEq(uint256(capabilities[0].responseType), uint256(CapabilityRegistry.CapabilityResponseType.REPORT)); + assertEq(capabilities[0].configurationContract, address(0)); + + assertEq(capabilities[1].capabilityType, "read-ethereum-mainnet-gas-price"); + assertEq(capabilities[1].version, "1.0.2"); + assertEq( + uint256(capabilities[1].responseType), + uint256(CapabilityRegistry.CapabilityResponseType.OBSERVATION_IDENTICAL) + ); + assertEq(capabilities[1].configurationContract, address(s_capabilityConfigurationContract)); + } + + function test_ExcludesDeprecatedCapabilities() public { + bytes32 capabilityId = s_capabilityRegistry.getCapabilityID( + s_basicCapability.capabilityType, + s_basicCapability.version + ); + s_capabilityRegistry.deprecateCapability(capabilityId); + + CapabilityRegistry.Capability[] memory capabilities = s_capabilityRegistry.getCapabilities(); + assertEq(capabilities.length, 1); + + assertEq(capabilities[0].capabilityType, "read-ethereum-mainnet-gas-price"); + assertEq(capabilities[0].version, "1.0.2"); + assertEq( + uint256(capabilities[0].responseType), + uint256(CapabilityRegistry.CapabilityResponseType.OBSERVATION_IDENTICAL) + ); + assertEq(capabilities[0].configurationContract, address(s_capabilityConfigurationContract)); + } +} diff --git a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go index d1f789f4408..4bac3789a33 100644 --- a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go +++ b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go @@ -43,8 +43,8 @@ type CapabilityRegistryNodeOperator struct { } var CapabilityRegistryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"lengthOne\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lengthTwo\",\"type\":\"uint256\"}],\"name\":\"LengthMismatch\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilities\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityID\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"updateNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6118e3806101576000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c806365c14dc7116100815780639cb7c5f41161005b5780639cb7c5f4146101e0578063ddbe4f8214610200578063f2fde38b1461021557600080fd5b806365c14dc71461019057806379ba5097146101b05780638da5cb5b146101b857600080fd5b80631cdf6343116100b25780631cdf634314610149578063229111f51461015c578063398f37731461017d57600080fd5b80630c5801e3146100d9578063117392ce146100ee578063181f5a7714610101575b600080fd5b6100ec6100e736600461108f565b610228565b005b6100ec6100fc3660046110fb565b610539565b604080518082018252601881527f4361706162696c697479526567697374727920312e302e300000000000000000602082015290516101409190611177565b60405180910390f35b6100ec61015736600461118a565b61076a565b61016f61016a3660046111cc565b61082d565b604051908152602001610140565b6100ec61018b36600461118a565b61085c565b6101a361019e3660046111ee565b6109f5565b6040516101409190611207565b6100ec610adb565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610140565b6101f36101ee3660046111ee565b610bd8565b60405161014091906112e9565b610208610c82565b60405161014091906112f7565b6100ec610223366004611367565b610d8a565b828114610270576040517fab8b67c600000000000000000000000000000000000000000000000000000000815260048101849052602481018290526044015b60405180910390fd5b6000805473ffffffffffffffffffffffffffffffffffffffff16905b848110156105315760008686838181106102a8576102a8611384565b90506020020135905060008585848181106102c5576102c5611384565b90506020028101906102d791906113b3565b6102e090611498565b805190915073ffffffffffffffffffffffffffffffffffffffff16610331576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16331480159061036e57503373ffffffffffffffffffffffffffffffffffffffff851614155b156103a5576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160008381526005602052604090205473ffffffffffffffffffffffffffffffffffffffff908116911614158061045757506020808201516040516103eb9201611177565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012060008681526005835292909220919261043e9260010191016115b1565b6040516020818303038152906040528051906020012014155b1561051e578051600083815260056020908152604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921782558201516001909101906104c490826116a0565b50806000015173ffffffffffffffffffffffffffffffffffffffff167f14c8f513e8a6d86d2d16b0cb64976de4e72386c4f8068eca3b7354373f8fe97a8383602001516040516105159291906117ba565b60405180910390a25b50508061052a906117d3565b905061028c565b505050505050565b610541610d9e565b60006105528235602084013561082d565b905061055f600382610e21565b15610596576040517fe288638f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006105a86080840160608501611367565b73ffffffffffffffffffffffffffffffffffffffff1614610713576105d36080830160608401611367565b73ffffffffffffffffffffffffffffffffffffffff163b15806106b357506106016080830160608401611367565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f884efe6100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff91909116906301ffc9a790602401602060405180830381865afa15801561068d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b19190611832565b155b15610713576106c86080830160608401611367565b6040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610267565b61071e600382610e3c565b50600081815260026020526040902082906107398282611854565b505060405181907f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff0690600090a25050565b610772610d9e565b60005b8181101561082857600083838381811061079157610791611384565b60209081029290920135600081815260059093526040832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559093509190506107e26001830182610ff5565b50506040518181527f1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f9060200160405180910390a150610821816117d3565b9050610775565b505050565b604080516020808201859052818301849052825180830384018152606090920190925280519101205b92915050565b610864610d9e565b60005b8181101561082857600083838381811061088357610883611384565b905060200281019061089591906113b3565b61089e90611498565b805190915073ffffffffffffffffffffffffffffffffffffffff166108ef576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600654604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526005909252939020825181547fffffffffffffffffffffffff00000000000000000000000000000000000000001692169190911781559151909190600182019061097290826116a0565b50905050600660008154610985906117d3565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b916109da918591906117ba565b60405180910390a25050806109ee906117d3565b9050610867565b6040805180820190915260008152606060208201526000828152600560209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610a5290611564565b80601f0160208091040260200160405190810160405280929190818152602001828054610a7e90611564565b8015610acb5780601f10610aa057610100808354040283529160200191610acb565b820191906000526020600020905b815481529060010190602001808311610aae57829003601f168201915b5050505050815250509050919050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610b5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610267565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b604080516080808201835260008083526020808401829052838501829052606084018290528582526002808252918590208551938401865280548452600180820154928501929092529182015493949293919284019160ff1690811115610c4157610c4161124a565b6001811115610c5257610c5261124a565b815260029190910154610100900473ffffffffffffffffffffffffffffffffffffffff1660209091015292915050565b60606000610c906003610e48565b90506000815167ffffffffffffffff811115610cae57610cae6113f1565b604051908082528060200260200182016040528015610d1e57816020015b6040805160808101825260008082526020808301829052928201819052606082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181610ccc5790505b50905060005b8251811015610d83576000838281518110610d4157610d41611384565b60200260200101519050610d5481610bd8565b838381518110610d6657610d66611384565b60200260200101819052505080610d7c906117d3565b9050610d24565b5092915050565b610d92610d9e565b610d9b81610e55565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610e1f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610267565b565b600081815260018301602052604081205415155b9392505050565b6000610e358383610f4a565b60606000610e3583610f99565b3373ffffffffffffffffffffffffffffffffffffffff821603610ed4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610267565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000818152600183016020526040812054610f9157508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610856565b506000610856565b606081600001805480602002602001604051908101604052809291908181526020018280548015610fe957602002820191906000526020600020905b815481526020019060010190808311610fd5575b50505050509050919050565b50805461100190611564565b6000825580601f10611011575050565b601f016020900490600052602060002090810190610d9b91905b8082111561103f576000815560010161102b565b5090565b60008083601f84011261105557600080fd5b50813567ffffffffffffffff81111561106d57600080fd5b6020830191508360208260051b850101111561108857600080fd5b9250929050565b600080600080604085870312156110a557600080fd5b843567ffffffffffffffff808211156110bd57600080fd5b6110c988838901611043565b909650945060208701359150808211156110e257600080fd5b506110ef87828801611043565b95989497509550505050565b60006080828403121561110d57600080fd5b50919050565b6000815180845260005b818110156111395760208185018101518683018201520161111d565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610e356020830184611113565b6000806020838503121561119d57600080fd5b823567ffffffffffffffff8111156111b457600080fd5b6111c085828601611043565b90969095509350505050565b600080604083850312156111df57600080fd5b50508035926020909101359150565b60006020828403121561120057600080fd5b5035919050565b6020815273ffffffffffffffffffffffffffffffffffffffff8251166020820152600060208301516040808401526112426060840182611113565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b80518252602081015160208301526040810151600281106112c3577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b604083015260609081015173ffffffffffffffffffffffffffffffffffffffff16910152565b608081016108568284611279565b6020808252825182820181905260009190848201906040850190845b8181101561133957611326838551611279565b9284019260809290920191600101611313565b50909695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610d9b57600080fd5b60006020828403121561137957600080fd5b8135610e3581611345565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126113e757600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611443576114436113f1565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611490576114906113f1565b604052919050565b6000604082360312156114aa57600080fd5b6114b2611420565b82356114bd81611345565b815260208381013567ffffffffffffffff808211156114db57600080fd5b9085019036601f8301126114ee57600080fd5b813581811115611500576115006113f1565b611530847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611449565b9150808252368482850101111561154657600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c9082168061157857607f821691505b60208210810361110d577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006020808352600084546115c581611564565b808487015260406001808416600081146115e6576001811461161e5761164c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a0101955061164c565b896000528660002060005b858110156116445781548b8201860152908301908801611629565b8a0184019650505b509398975050505050505050565b601f82111561082857600081815260208120601f850160051c810160208610156116815750805b601f850160051c820191505b818110156105315782815560010161168d565b815167ffffffffffffffff8111156116ba576116ba6113f1565b6116ce816116c88454611564565b8461165a565b602080601f83116001811461172157600084156116eb5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610531565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561176e5788860151825594840194600190910190840161174f565b50858210156117aa57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8281526040602082015260006112426040830184611113565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361182b577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b60006020828403121561184457600080fd5b81518015158114610e3557600080fd5b81358155602082013560018201556002810160408301356002811061187857600080fd5b8154606085013561188881611345565b74ffffffffffffffffffffffffffffffffffffffff008160081b1660ff84167fffffffffffffffffffffff00000000000000000000000000000000000000000084161717845550505050505056fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAlreadyDeprecated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"lengthOne\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lengthTwo\",\"type\":\"uint256\"}],\"name\":\"LengthMismatch\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDeprecated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"deprecateCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilities\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityID\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"isCapabilityDeprecated\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"updateNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611a7d80620001586000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c806365c14dc71161008c5780639cb7c5f4116100665780639cb7c5f41461023c578063ae3c241c1461025c578063ddbe4f821461026f578063f2fde38b1461028457600080fd5b806365c14dc7146101ec57806379ba50971461020c5780638da5cb5b1461021457600080fd5b8063181f5a77116100c8578063181f5a771461013f5780631cdf63431461017e578063229111f514610191578063398f3773146101d957600080fd5b80630c5801e3146100ef578063117392ce146101045780631257001114610117575b600080fd5b6101026100fd36600461120e565b610297565b005b61010261011236600461127a565b6105a8565b61012a610125366004611292565b6107f3565b60405190151581526020015b60405180910390f35b604080518082018252601881527f4361706162696c697479526567697374727920312e302e30000000000000000060208201529051610136919061130f565b61010261018c366004611322565b610806565b6101cb61019f366004611364565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b604051908152602001610136565b6101026101e7366004611322565b6108c9565b6101ff6101fa366004611292565b610a62565b6040516101369190611386565b610102610b48565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610136565b61024f61024a366004611292565b610c45565b6040516101369190611468565b61010261026a366004611292565b610cef565b610277610dba565b6040516101369190611476565b6101026102923660046114e6565b610eff565b8281146102df576040517fab8b67c600000000000000000000000000000000000000000000000000000000815260048101849052602481018290526044015b60405180910390fd5b6000805473ffffffffffffffffffffffffffffffffffffffff16905b848110156105a057600086868381811061031757610317611503565b905060200201359050600085858481811061033457610334611503565b90506020028101906103469190611532565b61034f90611617565b805190915073ffffffffffffffffffffffffffffffffffffffff166103a0576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff1633148015906103dd57503373ffffffffffffffffffffffffffffffffffffffff851614155b15610414576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160008381526007602052604090205473ffffffffffffffffffffffffffffffffffffffff90811691161415806104c6575060208082015160405161045a920161130f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206000868152600783529290922091926104ad926001019101611730565b6040516020818303038152906040528051906020012014155b1561058d578051600083815260076020908152604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909316929092178255820151600190910190610533908261181f565b50806000015173ffffffffffffffffffffffffffffffffffffffff167f14c8f513e8a6d86d2d16b0cb64976de4e72386c4f8068eca3b7354373f8fe97a838360200151604051610584929190611939565b60405180910390a25b50508061059990611981565b90506102fb565b505050505050565b6105b0610f13565b6040805182356020828101919091528084013582840152825180830384018152606090920190925280519101206105e8600382610f96565b1561061f576040517fe288638f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061063160808401606085016114e6565b73ffffffffffffffffffffffffffffffffffffffff161461079c5761065c60808301606084016114e6565b73ffffffffffffffffffffffffffffffffffffffff163b158061073c575061068a60808301606084016114e6565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f884efe6100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff91909116906301ffc9a790602401602060405180830381865afa158015610716573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073a91906119b9565b155b1561079c5761075160808301606084016114e6565b6040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016102d6565b6107a7600382610fb1565b50600081815260026020526040902082906107c282826119db565b505060405181907f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff0690600090a25050565b6000610800600583610f96565b92915050565b61080e610f13565b60005b818110156108c457600083838381811061082d5761082d611503565b60209081029290920135600081815260079093526040832080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815590935091905061087e6001830182611174565b50506040518181527f1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f9060200160405180910390a1506108bd81611981565b9050610811565b505050565b6108d1610f13565b60005b818110156108c45760008383838181106108f0576108f0611503565b90506020028101906109029190611532565b61090b90611617565b805190915073ffffffffffffffffffffffffffffffffffffffff1661095c576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600854604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526007909252939020825181547fffffffffffffffffffffffff0000000000000000000000000000000000000000169216919091178155915190919060018201906109df908261181f565b509050506008600081546109f290611981565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b91610a4791859190611939565b60405180910390a2505080610a5b90611981565b90506108d4565b6040805180820190915260008152606060208201526000828152600760209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610abf906116e3565b80601f0160208091040260200160405190810160405280929190818152602001828054610aeb906116e3565b8015610b385780601f10610b0d57610100808354040283529160200191610b38565b820191906000526020600020905b815481529060010190602001808311610b1b57829003601f168201915b5050505050815250509050919050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610bc9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016102d6565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b604080516080808201835260008083526020808401829052838501829052606084018290528582526002808252918590208551938401865280548452600180820154928501929092529182015493949293919284019160ff1690811115610cae57610cae6113c9565b6001811115610cbf57610cbf6113c9565b815260029190910154610100900473ffffffffffffffffffffffffffffffffffffffff1660209091015292915050565b610cf7610f13565b610d02600382610f96565b610d3b576040517fe181733f000000000000000000000000000000000000000000000000000000008152600481018290526024016102d6565b610d46600582610f96565b15610d80576040517f16950d1d000000000000000000000000000000000000000000000000000000008152600481018290526024016102d6565b610d8b600582610fb1565b5060405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf2190600090a250565b60606000610dc86003610fbd565b90506000610dd66005610fca565b8251610de29190611a5d565b67ffffffffffffffff811115610dfa57610dfa611570565b604051908082528060200260200182016040528015610e6a57816020015b6040805160808101825260008082526020808301829052928201819052606082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181610e185790505b5090506000805b8351811015610ef6576000848281518110610e8e57610e8e611503565b60200260200101519050610eac816005610f9690919063ffffffff16565b610ee557610eb981610c45565b848481518110610ecb57610ecb611503565b60200260200101819052508280610ee190611981565b9350505b50610eef81611981565b9050610e71565b50909392505050565b610f07610f13565b610f1081610fd4565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610f94576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016102d6565b565b600081815260018301602052604081205415155b9392505050565b6000610faa83836110c9565b60606000610faa83611118565b6000610800825490565b3373ffffffffffffffffffffffffffffffffffffffff821603611053576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016102d6565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600081815260018301602052604081205461111057508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610800565b506000610800565b60608160000180548060200260200160405190810160405280929190818152602001828054801561116857602002820191906000526020600020905b815481526020019060010190808311611154575b50505050509050919050565b508054611180906116e3565b6000825580601f10611190575050565b601f016020900490600052602060002090810190610f1091905b808211156111be57600081556001016111aa565b5090565b60008083601f8401126111d457600080fd5b50813567ffffffffffffffff8111156111ec57600080fd5b6020830191508360208260051b850101111561120757600080fd5b9250929050565b6000806000806040858703121561122457600080fd5b843567ffffffffffffffff8082111561123c57600080fd5b611248888389016111c2565b9096509450602087013591508082111561126157600080fd5b5061126e878288016111c2565b95989497509550505050565b60006080828403121561128c57600080fd5b50919050565b6000602082840312156112a457600080fd5b5035919050565b6000815180845260005b818110156112d1576020818501810151868301820152016112b5565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610faa60208301846112ab565b6000806020838503121561133557600080fd5b823567ffffffffffffffff81111561134c57600080fd5b611358858286016111c2565b90969095509350505050565b6000806040838503121561137757600080fd5b50508035926020909101359150565b6020815273ffffffffffffffffffffffffffffffffffffffff8251166020820152600060208301516040808401526113c160608401826112ab565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8051825260208101516020830152604081015160028110611442577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b604083015260609081015173ffffffffffffffffffffffffffffffffffffffff16910152565b6080810161080082846113f8565b6020808252825182820181905260009190848201906040850190845b818110156114b8576114a58385516113f8565b9284019260809290920191600101611492565b50909695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f1057600080fd5b6000602082840312156114f857600080fd5b8135610faa816114c4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261156657600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156115c2576115c2611570565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561160f5761160f611570565b604052919050565b60006040823603121561162957600080fd5b61163161159f565b823561163c816114c4565b815260208381013567ffffffffffffffff8082111561165a57600080fd5b9085019036601f83011261166d57600080fd5b81358181111561167f5761167f611570565b6116af847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016115c8565b915080825236848285010111156116c557600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c908216806116f757607f821691505b60208210810361128c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454611744816116e3565b80848701526040600180841660008114611765576001811461179d576117cb565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a010195506117cb565b896000528660002060005b858110156117c35781548b82018601529083019088016117a8565b8a0184019650505b509398975050505050505050565b601f8211156108c457600081815260208120601f850160051c810160208610156118005750805b601f850160051c820191505b818110156105a05782815560010161180c565b815167ffffffffffffffff81111561183957611839611570565b61184d8161184784546116e3565b846117d9565b602080601f8311600181146118a0576000841561186a5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556105a0565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156118ed578886015182559484019460019091019084016118ce565b508582101561192957878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8281526040602082015260006113c160408301846112ab565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036119b2576119b2611952565b5060010190565b6000602082840312156119cb57600080fd5b81518015158114610faa57600080fd5b8135815560208201356001820155600281016040830135600281106119ff57600080fd5b81546060850135611a0f816114c4565b74ffffffffffffffffffffffffffffffffffffffff008160081b1660ff84167fffffffffffffffffffffff000000000000000000000000000000000000000000841617178455505050505050565b818103818111156108005761080061195256fea164736f6c6343000813000a", } var CapabilityRegistryABI = CapabilityRegistryMetaData.ABI @@ -271,6 +271,28 @@ func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetNodeOperator(node return _CapabilityRegistry.Contract.GetNodeOperator(&_CapabilityRegistry.CallOpts, nodeOperatorId) } +func (_CapabilityRegistry *CapabilityRegistryCaller) IsCapabilityDeprecated(opts *bind.CallOpts, capabilityId [32]byte) (bool, error) { + var out []interface{} + err := _CapabilityRegistry.contract.Call(opts, &out, "isCapabilityDeprecated", capabilityId) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_CapabilityRegistry *CapabilityRegistrySession) IsCapabilityDeprecated(capabilityId [32]byte) (bool, error) { + return _CapabilityRegistry.Contract.IsCapabilityDeprecated(&_CapabilityRegistry.CallOpts, capabilityId) +} + +func (_CapabilityRegistry *CapabilityRegistryCallerSession) IsCapabilityDeprecated(capabilityId [32]byte) (bool, error) { + return _CapabilityRegistry.Contract.IsCapabilityDeprecated(&_CapabilityRegistry.CallOpts, capabilityId) +} + func (_CapabilityRegistry *CapabilityRegistryCaller) Owner(opts *bind.CallOpts) (common.Address, error) { var out []interface{} err := _CapabilityRegistry.contract.Call(opts, &out, "owner") @@ -351,6 +373,18 @@ func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AddNodeOperators return _CapabilityRegistry.Contract.AddNodeOperators(&_CapabilityRegistry.TransactOpts, nodeOperators) } +func (_CapabilityRegistry *CapabilityRegistryTransactor) DeprecateCapability(opts *bind.TransactOpts, capabilityId [32]byte) (*types.Transaction, error) { + return _CapabilityRegistry.contract.Transact(opts, "deprecateCapability", capabilityId) +} + +func (_CapabilityRegistry *CapabilityRegistrySession) DeprecateCapability(capabilityId [32]byte) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.DeprecateCapability(&_CapabilityRegistry.TransactOpts, capabilityId) +} + +func (_CapabilityRegistry *CapabilityRegistryTransactorSession) DeprecateCapability(capabilityId [32]byte) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.DeprecateCapability(&_CapabilityRegistry.TransactOpts, capabilityId) +} + func (_CapabilityRegistry *CapabilityRegistryTransactor) RemoveNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []*big.Int) (*types.Transaction, error) { return _CapabilityRegistry.contract.Transact(opts, "removeNodeOperators", nodeOperatorIds) } @@ -514,6 +548,133 @@ func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseCapabilityAdded(log return event, nil } +type CapabilityRegistryCapabilityDeprecatedIterator struct { + Event *CapabilityRegistryCapabilityDeprecated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilityRegistryCapabilityDeprecatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryCapabilityDeprecated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryCapabilityDeprecated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CapabilityRegistryCapabilityDeprecatedIterator) Error() error { + return it.fail +} + +func (it *CapabilityRegistryCapabilityDeprecatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilityRegistryCapabilityDeprecated struct { + CapabilityId [32]byte + Raw types.Log +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterCapabilityDeprecated(opts *bind.FilterOpts, capabilityId [][32]byte) (*CapabilityRegistryCapabilityDeprecatedIterator, error) { + + var capabilityIdRule []interface{} + for _, capabilityIdItem := range capabilityId { + capabilityIdRule = append(capabilityIdRule, capabilityIdItem) + } + + logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "CapabilityDeprecated", capabilityIdRule) + if err != nil { + return nil, err + } + return &CapabilityRegistryCapabilityDeprecatedIterator{contract: _CapabilityRegistry.contract, event: "CapabilityDeprecated", logs: logs, sub: sub}, nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchCapabilityDeprecated(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityDeprecated, capabilityId [][32]byte) (event.Subscription, error) { + + var capabilityIdRule []interface{} + for _, capabilityIdItem := range capabilityId { + capabilityIdRule = append(capabilityIdRule, capabilityIdItem) + } + + logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "CapabilityDeprecated", capabilityIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilityRegistryCapabilityDeprecated) + if err := _CapabilityRegistry.contract.UnpackLog(event, "CapabilityDeprecated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseCapabilityDeprecated(log types.Log) (*CapabilityRegistryCapabilityDeprecated, error) { + event := new(CapabilityRegistryCapabilityDeprecated) + if err := _CapabilityRegistry.contract.UnpackLog(event, "CapabilityDeprecated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type CapabilityRegistryNodeOperatorAddedIterator struct { Event *CapabilityRegistryNodeOperatorAdded @@ -1165,6 +1326,8 @@ func (_CapabilityRegistry *CapabilityRegistry) ParseLog(log types.Log) (generate switch log.Topics[0] { case _CapabilityRegistry.abi.Events["CapabilityAdded"].ID: return _CapabilityRegistry.ParseCapabilityAdded(log) + case _CapabilityRegistry.abi.Events["CapabilityDeprecated"].ID: + return _CapabilityRegistry.ParseCapabilityDeprecated(log) case _CapabilityRegistry.abi.Events["NodeOperatorAdded"].ID: return _CapabilityRegistry.ParseNodeOperatorAdded(log) case _CapabilityRegistry.abi.Events["NodeOperatorRemoved"].ID: @@ -1185,6 +1348,10 @@ func (CapabilityRegistryCapabilityAdded) Topic() common.Hash { return common.HexToHash("0x65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff06") } +func (CapabilityRegistryCapabilityDeprecated) Topic() common.Hash { + return common.HexToHash("0xdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf21") +} + func (CapabilityRegistryNodeOperatorAdded) Topic() common.Hash { return common.HexToHash("0xda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b") } @@ -1218,6 +1385,8 @@ type CapabilityRegistryInterface interface { GetNodeOperator(opts *bind.CallOpts, nodeOperatorId *big.Int) (CapabilityRegistryNodeOperator, error) + IsCapabilityDeprecated(opts *bind.CallOpts, capabilityId [32]byte) (bool, error) + Owner(opts *bind.CallOpts) (common.Address, error) TypeAndVersion(opts *bind.CallOpts) (string, error) @@ -1228,6 +1397,8 @@ type CapabilityRegistryInterface interface { AddNodeOperators(opts *bind.TransactOpts, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) + DeprecateCapability(opts *bind.TransactOpts, capabilityId [32]byte) (*types.Transaction, error) + RemoveNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []*big.Int) (*types.Transaction, error) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) @@ -1240,6 +1411,12 @@ type CapabilityRegistryInterface interface { ParseCapabilityAdded(log types.Log) (*CapabilityRegistryCapabilityAdded, error) + FilterCapabilityDeprecated(opts *bind.FilterOpts, capabilityId [][32]byte) (*CapabilityRegistryCapabilityDeprecatedIterator, error) + + WatchCapabilityDeprecated(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityDeprecated, capabilityId [][32]byte) (event.Subscription, error) + + ParseCapabilityDeprecated(log types.Log) (*CapabilityRegistryCapabilityDeprecated, error) + FilterNodeOperatorAdded(opts *bind.FilterOpts, admin []common.Address) (*CapabilityRegistryNodeOperatorAddedIterator, error) WatchNodeOperatorAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeOperatorAdded, admin []common.Address) (event.Subscription, error) diff --git a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt index efe3e4eaf90..0dff3f2986e 100644 --- a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,4 +1,4 @@ GETH_VERSION: 1.13.8 forwarder: ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.bin b4c900aae9e022f01abbac7993d41f93912247613ac6270b0c4da4ef6f2016e3 -keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin ae9e077854854fa066746eaa354324c7dac2a13bc38b81a66c856fddfc3b79bf +keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin 28fb0e1c437b97271d999f3b028f7bd44558352ec83f89501aabf501fcc915f1 ocr3_capability: ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.bin 9dcbdf55bd5729ba266148da3f17733eb592c871c2108ccca546618628fd9ad2 From 60a800b076ac359e78fd57c79ce6f1b9ef870e59 Mon Sep 17 00:00:00 2001 From: Jordan Krage Date: Tue, 30 Apr 2024 07:40:53 -0500 Subject: [PATCH 15/45] mockery cleanup (#13019) --- .tool-versions | 2 +- common/types/mocks/subscription.go | 2 +- common/types/subscription.go | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.tool-versions b/.tool-versions index 4aa55bda3f5..9db7d9b080d 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,5 +1,5 @@ golang 1.21.7 -mockery 2.38.0 +mockery 2.42.2 nodejs 16.16.0 pnpm 8.11.0 postgres 13.3 diff --git a/common/types/mocks/subscription.go b/common/types/mocks/subscription.go index 32db6dfa769..e52fafa7ca5 100644 --- a/common/types/mocks/subscription.go +++ b/common/types/mocks/subscription.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. +// Code generated by mockery v2.42.2. DO NOT EDIT. package mocks diff --git a/common/types/subscription.go b/common/types/subscription.go index 36d41ce1a20..e0cd0a1660d 100644 --- a/common/types/subscription.go +++ b/common/types/subscription.go @@ -1,9 +1,10 @@ package types +//go:generate mockery --quiet --name Subscription --output ./mocks/ --case=underscore + // Subscription represents an event subscription where events are // delivered on a data channel. // This is a generic interface for Subscription to represent used by clients. - type Subscription interface { // Unsubscribe cancels the sending of events to the data channel // and closes the error channel. From 5b87de0d4de8d572e1d9a2088cac7e0af7b85027 Mon Sep 17 00:00:00 2001 From: frank zhu Date: Tue, 30 Apr 2024 07:02:10 -0700 Subject: [PATCH 16/45] delete changeset workflow comment when conditions met (#13049) --- .github/workflows/changeset.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/changeset.yml b/.github/workflows/changeset.yml index 0af608624b1..c9b557a8bc9 100644 --- a/.github/workflows/changeset.yml +++ b/.github/workflows/changeset.yml @@ -60,7 +60,7 @@ jobs: - name: Make a comment uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 # v2.5.0 - if: ${{ (steps.files-changed.outputs.core == 'true' || steps.files-changed.outputs.shared == 'true') && steps.files-changed.outputs.core-changeset == 'false' }} + if: ${{ steps.files-changed.outputs.core == 'true' || steps.files-changed.outputs.shared == 'true' }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: @@ -69,10 +69,12 @@ jobs: ${{ env.TAGS }} reactions: eyes comment_tag: changeset-core + mode: ${{ steps.files-changed.outputs.core-changeset == 'false' && 'upsert' || 'delete' }} + create_if_not_exists: ${{ steps.files-changed.outputs.core-changeset == 'false' && 'true' || 'false' }} - name: Make a comment uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 # v2.5.0 - if: ${{ steps.files-changed.outputs.contracts == 'true' && steps.files-changed.outputs.contracts-changeset == 'false' }} + if: ${{ steps.files-changed.outputs.contracts == 'true' }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: @@ -80,6 +82,8 @@ jobs: I see you updated files related to `contracts`. Please run `pnpm changeset` in the `contracts` directory to add a changeset. reactions: eyes comment_tag: changeset-contracts + mode: ${{ steps.files-changed.outputs.contracts-changeset == 'false' && 'upsert' || 'delete' }} + create_if_not_exists: ${{ steps.files-changed.outputs.contracts-changeset == 'false' && 'true' || 'false' }} - name: Check for new changeset for core if: ${{ (steps.files-changed.outputs.core == 'true' || steps.files-changed.outputs.shared == 'true') && steps.files-changed.outputs.core-changeset == 'false' }} @@ -103,7 +107,7 @@ jobs: - name: Make a comment uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 # v2.5.0 - if: ${{ steps.files-changed.outputs.core-changeset == 'true' && steps.changeset-tags.outputs.has_tags == 'false' }} + if: ${{ steps.files-changed.outputs.core-changeset == 'true' }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: @@ -112,6 +116,8 @@ jobs: ${{ env.TAGS }} reactions: eyes comment_tag: changeset-core-tags + mode: ${{ steps.changeset-tags.outputs.has_tags == 'false' && 'upsert' || 'delete' }} + create_if_not_exists: ${{ steps.changeset-tags.outputs.has_tags == 'false' && 'true' || 'false' }} - name: Check for new changeset tags for core if: ${{ steps.files-changed.outputs.core-changeset == 'true' && steps.changeset-tags.outputs.has_tags == 'false' }} From 61106ec1ea6a4ab47ab0207088fa4f02bb1e3cc7 Mon Sep 17 00:00:00 2001 From: Jordan Krage Date: Tue, 30 Apr 2024 09:48:04 -0500 Subject: [PATCH 17/45] context cleanup (#13047) --- common/client/poller.go | 3 +-- core/internal/testutils/pgtest/txdb.go | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/common/client/poller.go b/common/client/poller.go index b21f28fe604..ebdcbd66283 100644 --- a/common/client/poller.go +++ b/common/client/poller.go @@ -78,8 +78,7 @@ func (p *Poller[T]) pollingLoop() { return case <-ticker.C: // Set polling timeout - pollingCtx, cancelPolling := context.WithTimeout(context.Background(), p.pollingTimeout) - p.stopCh.CtxCancel(pollingCtx, cancelPolling) + pollingCtx, cancelPolling := p.stopCh.CtxCancel(context.WithTimeout(context.Background(), p.pollingTimeout)) // Execute polling function result, err := p.pollingFunc(pollingCtx) cancelPolling() diff --git a/core/internal/testutils/pgtest/txdb.go b/core/internal/testutils/pgtest/txdb.go index 38fe8390bab..da9fd6cb2d0 100644 --- a/core/internal/testutils/pgtest/txdb.go +++ b/core/internal/testutils/pgtest/txdb.go @@ -19,7 +19,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/store/dialects" ) -// TODO still need to import this for side effects // txdb is a simplified version of https://github.com/DATA-DOG/go-txdb // // The original lib has various problems and is hard to understand because it From e50d38b0bddc34aa0b97ae6bdf23c355b5619682 Mon Sep 17 00:00:00 2001 From: HenryNguyen5 <6404866+HenryNguyen5@users.noreply.github.com> Date: Tue, 30 Apr 2024 11:26:23 -0400 Subject: [PATCH 18/45] Rename tags -> labels (#12961) --- .changeset/perfect-dancers-guess.md | 5 +++++ core/services/workflows/models_yaml.go | 22 +++++++++---------- .../workflows/marshalling/workflow_2.yaml | 2 +- .../fixtures/workflows/workflow_schema.json | 4 ++-- 4 files changed, 19 insertions(+), 14 deletions(-) create mode 100644 .changeset/perfect-dancers-guess.md diff --git a/.changeset/perfect-dancers-guess.md b/.changeset/perfect-dancers-guess.md new file mode 100644 index 00000000000..6ee4099c45a --- /dev/null +++ b/.changeset/perfect-dancers-guess.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal Rename workflow tags to labels diff --git a/core/services/workflows/models_yaml.go b/core/services/workflows/models_yaml.go index 3d65e24a814..280a895f1b8 100644 --- a/core/services/workflows/models_yaml.go +++ b/core/services/workflows/models_yaml.go @@ -172,8 +172,8 @@ type stepDefinitionYaml struct { // // Eventually, we might support minor version and specific version pins. This will allow workflow authors to have flexibility when selecting the version, and node operators will be able to determine when they should update their capabilities. // - // There are two ways to specify a type - using a string as a fully qualified ID or a structured table. When using a table, tags are ordered alphanumerically and joined into a string following a - // {type}:{tag1_key}_{tag1_value}:{tag2_key}_{tag2_value}@{version} + // There are two ways to specify a type - using a string as a fully qualified ID or a structured table. When using a table, labels are ordered alphanumerically and joined into a string following a + // {name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}@{version} // pattern. // // The “type” supports [a-z0-9_-:] characters followed by an @ and [semver regex] at the end. @@ -191,7 +191,7 @@ type stepDefinitionYaml struct { // type: // name: read_chain // version: 1 - // tags: + // labels: // chain: ethereum // network: mainnet // @@ -319,22 +319,22 @@ func (stepDefinitionType) JSONSchema() *jsonschema.Schema { type stepDefinitionTableType struct { Name string `json:"name"` Version string `json:"version" jsonschema:"pattern=(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"` - Tags map[string]string `json:"tags"` + Labels map[string]string `json:"labels"` } // String returns the string representation of a stepDefinitionTableType. // // It follows the format: // -// {name}:{tag1_key}_{tag1_value}:{tag2_key}_{tag2_value}@{version} +// {name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}@{version} // -// where tags are ordered alphanumerically. +// where labels are ordered alphanumerically. func (s stepDefinitionTableType) String() string { - tags := make([]string, 0, len(s.Tags)) - for k, v := range s.Tags { - tags = append(tags, fmt.Sprintf("%s_%s", k, v)) + labels := make([]string, 0, len(s.Labels)) + for k, v := range s.Labels { + labels = append(labels, fmt.Sprintf("%s_%s", k, v)) } - slices.Sort(tags) + slices.Sort(labels) - return fmt.Sprintf("%s:%s@%s", s.Name, strings.Join(tags, ":"), s.Version) + return fmt.Sprintf("%s:%s@%s", s.Name, strings.Join(labels, ":"), s.Version) } diff --git a/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2.yaml b/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2.yaml index f43cd291703..50a598d0bc9 100644 --- a/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2.yaml +++ b/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2.yaml @@ -9,7 +9,7 @@ - type: name: trigger_test version: "2" - tags: + labels: chain: ethereum aaShouldBeFirst: "true" network: mainnet diff --git a/core/services/workflows/testdata/fixtures/workflows/workflow_schema.json b/core/services/workflows/testdata/fixtures/workflows/workflow_schema.json index 2cb02c7921d..83ecd42ecb9 100644 --- a/core/services/workflows/testdata/fixtures/workflows/workflow_schema.json +++ b/core/services/workflows/testdata/fixtures/workflows/workflow_schema.json @@ -23,7 +23,7 @@ "type": "string", "pattern": "(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$" }, - "tags": { + "labels": { "additionalProperties": { "type": "string" }, @@ -35,7 +35,7 @@ "required": [ "name", "version", - "tags" + "labels" ] } ], From 2729ef76f34877a2e6e8644b2e67f3e5dfb0c2b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Tue, 30 Apr 2024 17:31:39 +0200 Subject: [PATCH 19/45] [SHIP-1523] Add X Layer (#12747) * Add X Layer * go mod tidy * Add ChainType for XLayer to ignore transactions with 0 gasPrice * revert switch stmt * update changeset * fix test * add BlockHistoryEstimator test for XLayer --- .changeset/sixty-readers-mix.md | 5 + common/config/chaintype.go | 4 +- .../config/toml/defaults/XLayer_Mainnet.toml | 25 +++ .../config/toml/defaults/XLayer_Sepolia.toml | 25 +++ .../evm/gas/block_history_estimator_test.go | 5 + core/chains/evm/gas/chain_specific.go | 4 +- core/config/docs/chains-evm.toml | 2 +- core/services/chainlink/config_test.go | 4 +- core/services/ocr/contract_tracker.go | 2 +- core/services/ocrcommon/block_translator.go | 2 +- docs/CONFIG.md | 172 +++++++++++++++++- 11 files changed, 241 insertions(+), 9 deletions(-) create mode 100644 .changeset/sixty-readers-mix.md create mode 100644 core/chains/evm/config/toml/defaults/XLayer_Mainnet.toml create mode 100644 core/chains/evm/config/toml/defaults/XLayer_Sepolia.toml diff --git a/.changeset/sixty-readers-mix.md b/.changeset/sixty-readers-mix.md new file mode 100644 index 00000000000..a6782a5b276 --- /dev/null +++ b/.changeset/sixty-readers-mix.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Add support for X Layer (X1) #added diff --git a/common/config/chaintype.go b/common/config/chaintype.go index 29bab2a91e2..73c48960a13 100644 --- a/common/config/chaintype.go +++ b/common/config/chaintype.go @@ -19,6 +19,7 @@ const ( ChainScroll ChainType = "scroll" ChainWeMix ChainType = "wemix" ChainXDai ChainType = "xdai" // Deprecated: use ChainGnosis instead + ChainXLayer ChainType = "xlayer" ChainZkSync ChainType = "zksync" ) @@ -31,13 +32,14 @@ var ErrInvalidChainType = fmt.Errorf("must be one of %s or omitted", strings.Joi string(ChainOptimismBedrock), string(ChainScroll), string(ChainWeMix), + string(ChainXLayer), string(ChainZkSync), }, ", ")) // IsValid returns true if the ChainType value is known or empty. func (c ChainType) IsValid() bool { switch c { - case "", ChainArbitrum, ChainCelo, ChainGnosis, ChainKroma, ChainMetis, ChainOptimismBedrock, ChainScroll, ChainWeMix, ChainXDai, ChainZkSync: + case "", ChainArbitrum, ChainCelo, ChainGnosis, ChainKroma, ChainMetis, ChainOptimismBedrock, ChainScroll, ChainWeMix, ChainXDai, ChainXLayer, ChainZkSync: return true } return false diff --git a/core/chains/evm/config/toml/defaults/XLayer_Mainnet.toml b/core/chains/evm/config/toml/defaults/XLayer_Mainnet.toml new file mode 100644 index 00000000000..4096a4db244 --- /dev/null +++ b/core/chains/evm/config/toml/defaults/XLayer_Mainnet.toml @@ -0,0 +1,25 @@ +ChainID = '196' +ChainType = 'xlayer' +FinalityDepth = 500 +NoNewHeadsThreshold = '6m' +MinIncomingConfirmations = 1 +LogPollInterval = '30s' +RPCBlockQueryDelay = 15 +RPCDefaultBatchSize = 100 + +[OCR] +ContractConfirmations = 1 + +[Transactions] +ResendAfterThreshold = '3m' + +[GasEstimator] +PriceMin = '100 mwei' +BumpPercent = 40 +BumpMin = '100 mwei' + +[GasEstimator.BlockHistory] +BlockHistorySize = 12 + +[HeadTracker] +HistoryDepth = 2000 diff --git a/core/chains/evm/config/toml/defaults/XLayer_Sepolia.toml b/core/chains/evm/config/toml/defaults/XLayer_Sepolia.toml new file mode 100644 index 00000000000..62e2c1e8ad0 --- /dev/null +++ b/core/chains/evm/config/toml/defaults/XLayer_Sepolia.toml @@ -0,0 +1,25 @@ +ChainID = '195' +ChainType = 'xlayer' +FinalityDepth = 500 +NoNewHeadsThreshold = '12m' +MinIncomingConfirmations = 1 +LogPollInterval = '30s' +RPCBlockQueryDelay = 15 +RPCDefaultBatchSize = 100 + +[OCR] +ContractConfirmations = 1 + +[Transactions] +ResendAfterThreshold = '3m' + +[GasEstimator] +PriceMin = '1 mwei' +BumpPercent = 40 +BumpMin = '20 mwei' + +[GasEstimator.BlockHistory] +BlockHistorySize = 12 + +[HeadTracker] +HistoryDepth = 2000 diff --git a/core/chains/evm/gas/block_history_estimator_test.go b/core/chains/evm/gas/block_history_estimator_test.go index 941b60545ba..43f42c69203 100644 --- a/core/chains/evm/gas/block_history_estimator_test.go +++ b/core/chains/evm/gas/block_history_estimator_test.go @@ -997,6 +997,11 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { cfg.ChainTypeF = string(config.ChainXDai) bhe.Recalculate(cltest.Head(0)) require.Equal(t, assets.NewWeiI(80), gas.GetGasPrice(bhe)) + + // And for X Layer + cfg.ChainTypeF = string(config.ChainXLayer) + bhe.Recalculate(cltest.Head(0)) + require.Equal(t, assets.NewWeiI(80), gas.GetGasPrice(bhe)) }) t.Run("handles unreasonably large gas prices (larger than a 64 bit int can hold)", func(t *testing.T) { diff --git a/core/chains/evm/gas/chain_specific.go b/core/chains/evm/gas/chain_specific.go index c64441cc142..694411f164b 100644 --- a/core/chains/evm/gas/chain_specific.go +++ b/core/chains/evm/gas/chain_specific.go @@ -9,9 +9,9 @@ import ( // chainSpecificIsUsable allows for additional logic specific to a particular // Config that determines whether a transaction should be used for gas estimation func chainSpecificIsUsable(tx evmtypes.Transaction, baseFee *assets.Wei, chainType config.ChainType, minGasPriceWei *assets.Wei) bool { - if chainType == config.ChainGnosis || chainType == config.ChainXDai { + if chainType == config.ChainGnosis || chainType == config.ChainXDai || chainType == config.ChainXLayer { // GasPrice 0 on most chains is great since it indicates cheap/free transactions. - // However, Gnosis reserves a special type of "bridge" transaction with 0 gas + // However, Gnosis and XLayer reserve a special type of "bridge" transaction with 0 gas // price that is always processed at top priority. Ordinary transactions // must be priced at least 1GWei, so we have to discard anything priced // below that (unless the contract is whitelisted). diff --git a/core/config/docs/chains-evm.toml b/core/config/docs/chains-evm.toml index 49c42bc04fb..49360caad21 100644 --- a/core/config/docs/chains-evm.toml +++ b/core/config/docs/chains-evm.toml @@ -14,7 +14,7 @@ BlockBackfillDepth = 10 # Default # BlockBackfillSkip enables skipping of very long backfills. BlockBackfillSkip = false # Default # ChainType is automatically detected from chain ID. Set this to force a certain chain type regardless of chain ID. -# Available types: `arbitrum`, `celo`, `gnosis`, `kroma`, `metis`, `optimismBedrock`, `scroll`, `wemix`, `zksync` +# Available types: `arbitrum`, `celo`, `gnosis`, `kroma`, `metis`, `optimismBedrock`, `scroll`, `wemix`, `xlayer`, `zksync` # # `xdai` has been deprecated and will be removed in v2.13.0, use `gnosis` instead. ChainType = 'arbitrum' # Example diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index 0d40697345d..11d286fbcd5 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -1264,7 +1264,7 @@ func TestConfig_Validate(t *testing.T) { - 1: 6 errors: - ChainType: invalid value (Foo): must not be set with this chain id - Nodes: missing: must have at least one node - - ChainType: invalid value (Foo): must be one of arbitrum, celo, gnosis, kroma, metis, optimismBedrock, scroll, wemix, zksync or omitted + - ChainType: invalid value (Foo): must be one of arbitrum, celo, gnosis, kroma, metis, optimismBedrock, scroll, wemix, xlayer, zksync or omitted - HeadTracker.HistoryDepth: invalid value (30): must be equal to or greater than FinalityDepth - GasEstimator: 2 errors: - FeeCapDefault: invalid value (101 wei): must be equal to PriceMax (99 wei) since you are using FixedPrice estimation with gas bumping disabled in EIP1559 mode - PriceMax will be used as the FeeCap for transactions instead of FeeCapDefault @@ -1273,7 +1273,7 @@ func TestConfig_Validate(t *testing.T) { - 2: 5 errors: - ChainType: invalid value (Arbitrum): only "optimismBedrock" can be used with this chain id - Nodes: missing: must have at least one node - - ChainType: invalid value (Arbitrum): must be one of arbitrum, celo, gnosis, kroma, metis, optimismBedrock, scroll, wemix, zksync or omitted + - ChainType: invalid value (Arbitrum): must be one of arbitrum, celo, gnosis, kroma, metis, optimismBedrock, scroll, wemix, xlayer, zksync or omitted - FinalityDepth: invalid value (0): must be greater than or equal to 1 - MinIncomingConfirmations: invalid value (0): must be greater than or equal to 1 - 3.Nodes: 5 errors: diff --git a/core/services/ocr/contract_tracker.go b/core/services/ocr/contract_tracker.go index f7c7a9940b5..1d9076b8322 100644 --- a/core/services/ocr/contract_tracker.go +++ b/core/services/ocr/contract_tracker.go @@ -400,7 +400,7 @@ func (t *OCRContractTracker) LatestBlockHeight(ctx context.Context) (blockheight // care about the block height; we have no way of getting the L1 block // height anyway return 0, nil - case "", config.ChainArbitrum, config.ChainCelo, config.ChainGnosis, config.ChainKroma, config.ChainOptimismBedrock, config.ChainScroll, config.ChainWeMix, config.ChainXDai, config.ChainZkSync: + case "", config.ChainArbitrum, config.ChainCelo, config.ChainGnosis, config.ChainKroma, config.ChainOptimismBedrock, config.ChainScroll, config.ChainWeMix, config.ChainXDai, config.ChainXLayer, config.ChainZkSync: // continue } latestBlockHeight := t.getLatestBlockHeight() diff --git a/core/services/ocrcommon/block_translator.go b/core/services/ocrcommon/block_translator.go index bc7242a6019..6ef64499fa9 100644 --- a/core/services/ocrcommon/block_translator.go +++ b/core/services/ocrcommon/block_translator.go @@ -21,7 +21,7 @@ func NewBlockTranslator(cfg Config, client evmclient.Client, lggr logger.Logger) switch cfg.ChainType() { case config.ChainArbitrum: return NewArbitrumBlockTranslator(client, lggr) - case "", config.ChainCelo, config.ChainGnosis, config.ChainKroma, config.ChainMetis, config.ChainOptimismBedrock, config.ChainScroll, config.ChainWeMix, config.ChainXDai, config.ChainZkSync: + case "", config.ChainCelo, config.ChainGnosis, config.ChainKroma, config.ChainMetis, config.ChainOptimismBedrock, config.ChainScroll, config.ChainWeMix, config.ChainXDai, config.ChainXLayer, config.ChainZkSync: fallthrough default: return &l1BlockTranslator{} diff --git a/docs/CONFIG.md b/docs/CONFIG.md index f93d990413f..61ba9256d9d 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -3005,6 +3005,176 @@ GasLimit = 5400000

+
XLayer Sepolia (195)

+ +```toml +AutoCreateKey = true +BlockBackfillDepth = 10 +BlockBackfillSkip = false +ChainType = 'xlayer' +FinalityDepth = 500 +FinalityTagEnabled = false +LogBackfillBatchSize = 1000 +LogPollInterval = '30s' +LogKeepBlocksDepth = 100000 +LogPrunePageSize = 0 +BackupLogPollerBlockDelay = 100 +MinIncomingConfirmations = 1 +MinContractPayment = '0.00001 link' +NonceAutoSync = true +NoNewHeadsThreshold = '12m0s' +RPCDefaultBatchSize = 100 +RPCBlockQueryDelay = 15 + +[Transactions] +ForwardersEnabled = false +MaxInFlight = 16 +MaxQueued = 250 +ReaperInterval = '1h0m0s' +ReaperThreshold = '168h0m0s' +ResendAfterThreshold = '3m0s' + +[BalanceMonitor] +Enabled = true + +[GasEstimator] +Mode = 'BlockHistory' +PriceDefault = '20 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +PriceMin = '1 mwei' +LimitDefault = 500000 +LimitMax = 500000 +LimitMultiplier = '1' +LimitTransfer = 21000 +BumpMin = '20 mwei' +BumpPercent = 40 +BumpThreshold = 3 +EIP1559DynamicFees = false +FeeCapDefault = '100 gwei' +TipCapDefault = '1 wei' +TipCapMin = '1 wei' + +[GasEstimator.BlockHistory] +BatchSize = 25 +BlockHistorySize = 12 +CheckInclusionBlocks = 12 +CheckInclusionPercentile = 90 +TransactionPercentile = 60 + +[HeadTracker] +HistoryDepth = 2000 +MaxBufferSize = 3 +SamplingInterval = '1s' + +[NodePool] +PollFailureThreshold = 5 +PollInterval = '10s' +SelectionMode = 'HighestHead' +SyncThreshold = 5 +LeaseDuration = '0s' +NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' + +[OCR] +ContractConfirmations = 1 +ContractTransmitterTransmitTimeout = '10s' +DatabaseTimeout = '10s' +DeltaCOverride = '168h0m0s' +DeltaCJitterOverride = '1h0m0s' +ObservationGracePeriod = '1s' + +[OCR2] +[OCR2.Automation] +GasLimit = 5400000 +``` + +

+ +
XLayer Mainnet (196)

+ +```toml +AutoCreateKey = true +BlockBackfillDepth = 10 +BlockBackfillSkip = false +ChainType = 'xlayer' +FinalityDepth = 500 +FinalityTagEnabled = false +LogBackfillBatchSize = 1000 +LogPollInterval = '30s' +LogKeepBlocksDepth = 100000 +LogPrunePageSize = 0 +BackupLogPollerBlockDelay = 100 +MinIncomingConfirmations = 1 +MinContractPayment = '0.00001 link' +NonceAutoSync = true +NoNewHeadsThreshold = '6m0s' +RPCDefaultBatchSize = 100 +RPCBlockQueryDelay = 15 + +[Transactions] +ForwardersEnabled = false +MaxInFlight = 16 +MaxQueued = 250 +ReaperInterval = '1h0m0s' +ReaperThreshold = '168h0m0s' +ResendAfterThreshold = '3m0s' + +[BalanceMonitor] +Enabled = true + +[GasEstimator] +Mode = 'BlockHistory' +PriceDefault = '20 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +PriceMin = '100 mwei' +LimitDefault = 500000 +LimitMax = 500000 +LimitMultiplier = '1' +LimitTransfer = 21000 +BumpMin = '100 mwei' +BumpPercent = 40 +BumpThreshold = 3 +EIP1559DynamicFees = false +FeeCapDefault = '100 gwei' +TipCapDefault = '1 wei' +TipCapMin = '1 wei' + +[GasEstimator.BlockHistory] +BatchSize = 25 +BlockHistorySize = 12 +CheckInclusionBlocks = 12 +CheckInclusionPercentile = 90 +TransactionPercentile = 60 + +[HeadTracker] +HistoryDepth = 2000 +MaxBufferSize = 3 +SamplingInterval = '1s' + +[NodePool] +PollFailureThreshold = 5 +PollInterval = '10s' +SelectionMode = 'HighestHead' +SyncThreshold = 5 +LeaseDuration = '0s' +NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' + +[OCR] +ContractConfirmations = 1 +ContractTransmitterTransmitTimeout = '10s' +DatabaseTimeout = '10s' +DeltaCOverride = '168h0m0s' +DeltaCJitterOverride = '1h0m0s' +ObservationGracePeriod = '1s' + +[OCR2] +[OCR2.Automation] +GasLimit = 5400000 +``` + +

+
Fantom Mainnet (250)

```toml @@ -6606,7 +6776,7 @@ BlockBackfillSkip enables skipping of very long backfills. ChainType = 'arbitrum' # Example ``` ChainType is automatically detected from chain ID. Set this to force a certain chain type regardless of chain ID. -Available types: `arbitrum`, `celo`, `gnosis`, `kroma`, `metis`, `optimismBedrock`, `scroll`, `wemix`, `zksync` +Available types: `arbitrum`, `celo`, `gnosis`, `kroma`, `metis`, `optimismBedrock`, `scroll`, `wemix`, `xlayer`, `zksync` `xdai` has been deprecated and will be removed in v2.13.0, use `gnosis` instead. From 55545bb1514dfcb83d103b3801ba5b8327252a1b Mon Sep 17 00:00:00 2001 From: Tate Date: Tue, 30 Apr 2024 15:58:17 -0600 Subject: [PATCH 20/45] Add job name to be required by golangci-lint action to fix metrics (#13054) --- .github/actions/golangci-lint/action.yml | 2 +- .github/workflows/ci-core.yml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/actions/golangci-lint/action.yml b/.github/actions/golangci-lint/action.yml index e52dd1aed7b..e667ade16eb 100644 --- a/.github/actions/golangci-lint/action.yml +++ b/.github/actions/golangci-lint/action.yml @@ -7,7 +7,7 @@ inputs: required: true name: description: Name of the lint action - default: lint + required: true go-directory: description: Go directory to run commands from default: "." diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml index e1891770930..fbef1b8282c 100644 --- a/.github/workflows/ci-core.yml +++ b/.github/workflows/ci-core.yml @@ -64,6 +64,7 @@ jobs: if: ${{ needs.filter.outputs.changes == 'true' }} with: id: core + name: lint gc-basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} gc-host: ${{ secrets.GRAFANA_INTERNAL_HOST }} gc-org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} From ea08b5f08d84d2ff1ddfa2027660ff58a60219c3 Mon Sep 17 00:00:00 2001 From: HenryNguyen5 <6404866+HenryNguyen5@users.noreply.github.com> Date: Tue, 30 Apr 2024 21:05:34 -0400 Subject: [PATCH 21/45] Fix some txdb comment typos (#13059) --- .changeset/spotty-cooks-think.md | 5 +++++ core/internal/testutils/pgtest/txdb.go | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 .changeset/spotty-cooks-think.md diff --git a/.changeset/spotty-cooks-think.md b/.changeset/spotty-cooks-think.md new file mode 100644 index 00000000000..e645de27beb --- /dev/null +++ b/.changeset/spotty-cooks-think.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal fix txdb documentation typos diff --git a/core/internal/testutils/pgtest/txdb.go b/core/internal/testutils/pgtest/txdb.go index da9fd6cb2d0..f4640946ad4 100644 --- a/core/internal/testutils/pgtest/txdb.go +++ b/core/internal/testutils/pgtest/txdb.go @@ -74,8 +74,8 @@ var _ driver.Conn = &conn{} var _ driver.Validator = &conn{} var _ driver.SessionResetter = &conn{} -// txDriver is an sql driver which runs on single transaction -// when the Close is called, transaction is rolled back +// txDriver is an sql driver which runs on a single transaction. +// When `Close` is called, transaction is rolled back. type txDriver struct { sync.Mutex db *sql.DB @@ -110,8 +110,8 @@ func (d *txDriver) Open(dsn string) (driver.Conn, error) { return c, nil } -// deleteConn is called by connection when it is closed -// It also auto-closes the DB when the last checked out connection is closed +// deleteConn is called by a connection when it is closed via the `close` method. +// It also auto-closes the DB when the last checked out connection is closed. func (d *txDriver) deleteConn(c *conn) error { // must lock here to avoid racing with Open d.Lock() From 2805fa6c9b469d535edcd3d66c08e1d22bbaa2d0 Mon Sep 17 00:00:00 2001 From: Christopher Dimitri Sastropranoto Date: Wed, 1 May 2024 22:41:46 +0700 Subject: [PATCH 22/45] Implement addNodes and getNode (#13022) * implement add node * Fix the test * Use p2pId for node identification. * Revert if node exists * supportedCapabilityIds string[] => bytes32[] * Revert when adding node without capabilities * Verify that supported capabilities exist in the registry * Create a variable for a non-existent capability. * Undo a change * Add p2pId to the event * Remove redundant comment * Regen wrappers * Switch to using bytes32 instead of bytes for p2pId * Add a comment about allowing deprecated capabilities * Add signer address to Node * Move checks around * Regen wrappers --------- Co-authored-by: DeividasK --- .changeset/thirty-students-explain.md | 5 + contracts/.changeset/tidy-stingrays-care.md | 5 + .../src/v0.8/keystone/CapabilityRegistry.sol | 67 ++++++- .../src/v0.8/keystone/test/BaseTest.t.sol | 14 +- .../CapabilityRegistry_AddNodesTest.t.sol | 136 +++++++++++++ ...pabilityRegistry_DeprecateCapability.t.sol | 8 +- .../src/v0.8/keystone/test/Constants.t.sol | 4 + .../keystone_capability_registry.go | 179 +++++++++++++++++- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 9 files changed, 411 insertions(+), 9 deletions(-) create mode 100644 .changeset/thirty-students-explain.md create mode 100644 contracts/.changeset/tidy-stingrays-care.md create mode 100644 contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol diff --git a/.changeset/thirty-students-explain.md b/.changeset/thirty-students-explain.md new file mode 100644 index 00000000000..0408383bd03 --- /dev/null +++ b/.changeset/thirty-students-explain.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal diff --git a/contracts/.changeset/tidy-stingrays-care.md b/contracts/.changeset/tidy-stingrays-care.md new file mode 100644 index 00000000000..9d376e40c05 --- /dev/null +++ b/contracts/.changeset/tidy-stingrays-care.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +#internal diff --git a/contracts/src/v0.8/keystone/CapabilityRegistry.sol b/contracts/src/v0.8/keystone/CapabilityRegistry.sol index 9d627c2afb5..ed3a300ac40 100644 --- a/contracts/src/v0.8/keystone/CapabilityRegistry.sol +++ b/contracts/src/v0.8/keystone/CapabilityRegistry.sol @@ -19,6 +19,21 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { string name; } + struct Node { + /// @notice The id of the node operator that manages this node + uint256 nodeOperatorId; + /// @notice This is an Ed25519 public key that is used to identify a node. + /// This key is guaranteed to be unique in the CapabilityRegistry. It is + /// used to identify a node in the the P2P network. + bytes32 p2pId; + /// @notice The signer address for application-layer message verification. + address signer; + /// @notice The list of capability IDs this node supports. This list is + /// never empty and all capabilities are guaranteed to exist in the + /// CapabilityRegistry. + bytes32[] supportedCapabilityIds; + } + // CapabilityResponseType indicates whether remote response requires // aggregation or is an already aggregated report. There are multiple // possible ways to aggregate. @@ -70,6 +85,21 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// admin address to the zero address error InvalidNodeOperatorAdmin(); + /// @notice This error is thrown when trying to add a node with P2P ID that + /// is empty bytes or a duplicate. + /// @param p2pId The provided P2P ID + error InvalidNodeP2PId(bytes32 p2pId); + + /// @notice This error is thrown when trying to add a node without + /// capabilities or with capabilities that do not exist. + /// @param capabilityIds The IDs of the capabilities that are being added. + error InvalidNodeCapabilities(bytes32[] capabilityIds); + + /// @notice This event is emitted when a new node is added + /// @param p2pId The P2P ID of the node + /// @param nodeOperatorId The ID of the node operator that manages this node + event NodeAdded(bytes32 p2pId, uint256 nodeOperatorId); + /// @notice This error is thrown when trying add a capability that already /// exists. error CapabilityAlreadyExists(); @@ -120,7 +150,10 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { EnumerableSet.Bytes32Set private s_deprecatedCapabilityIds; /// @notice Mapping of node operators - mapping(uint256 nodeOperatorId => NodeOperator) private s_nodeOperators; + mapping(uint256 nodeOperatorId => NodeOperator nodeOperator) private s_nodeOperators; + + /// @notice Mapping of nodes + mapping(bytes32 p2pId => Node node) private s_nodes; /// @notice The latest node operator ID /// @dev No getter for this as this is an implementation detail @@ -184,6 +217,38 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { return s_nodeOperators[nodeOperatorId]; } + /// @notice Adds nodes. Nodes can be added with deprecated capabilities to + /// avoid breaking changes when deprecating capabilities. + /// @param nodes The nodes to add + function addNodes(Node[] calldata nodes) external { + for (uint256 i; i < nodes.length; ++i) { + Node memory node = nodes[i]; + + NodeOperator memory nodeOperator = s_nodeOperators[node.nodeOperatorId]; + if (msg.sender != nodeOperator.admin) revert AccessForbidden(); + + bool nodeExists = s_nodes[node.p2pId].supportedCapabilityIds.length > 0; + if (nodeExists || bytes32(node.p2pId) == bytes32("")) revert InvalidNodeP2PId(node.p2pId); + + if (node.supportedCapabilityIds.length == 0) revert InvalidNodeCapabilities(node.supportedCapabilityIds); + + for (uint256 j; j < node.supportedCapabilityIds.length; ++j) { + if (!s_capabilityIds.contains(node.supportedCapabilityIds[j])) + revert InvalidNodeCapabilities(node.supportedCapabilityIds); + } + + s_nodes[node.p2pId] = node; + emit NodeAdded(node.p2pId, node.nodeOperatorId); + } + } + + /// @notice Gets a node's data + /// @param p2pId The P2P ID of the node to query for + /// @return Node The node data + function getNode(bytes32 p2pId) external view returns (Node memory) { + return s_nodes[p2pId]; + } + function addCapability(Capability calldata capability) external onlyOwner { bytes32 capabilityId = getCapabilityID(capability.capabilityType, capability.version); diff --git a/contracts/src/v0.8/keystone/test/BaseTest.t.sol b/contracts/src/v0.8/keystone/test/BaseTest.t.sol index a2b1b3a53eb..95c8d1e5d3d 100644 --- a/contracts/src/v0.8/keystone/test/BaseTest.t.sol +++ b/contracts/src/v0.8/keystone/test/BaseTest.t.sol @@ -11,6 +11,9 @@ contract BaseTest is Test, Constants { CapabilityConfigurationContract internal s_capabilityConfigurationContract; CapabilityRegistry.Capability internal s_basicCapability; CapabilityRegistry.Capability internal s_capabilityWithConfigurationContract; + bytes32 internal s_basicCapabilityId; + bytes32 internal s_capabilityWithConfigurationContractId; + bytes32 internal s_nonExistentCapabilityId; function setUp() public virtual { vm.startPrank(ADMIN); @@ -23,13 +26,22 @@ contract BaseTest is Test, Constants { responseType: CapabilityRegistry.CapabilityResponseType.REPORT, configurationContract: address(0) }); - s_capabilityWithConfigurationContract = CapabilityRegistry.Capability({ capabilityType: "read-ethereum-mainnet-gas-price", version: "1.0.2", responseType: CapabilityRegistry.CapabilityResponseType.OBSERVATION_IDENTICAL, configurationContract: address(s_capabilityConfigurationContract) }); + + s_basicCapabilityId = s_capabilityRegistry.getCapabilityID( + s_basicCapability.capabilityType, + s_basicCapability.version + ); + s_capabilityWithConfigurationContractId = s_capabilityRegistry.getCapabilityID( + s_capabilityWithConfigurationContract.capabilityType, + s_capabilityWithConfigurationContract.version + ); + s_nonExistentCapabilityId = s_capabilityRegistry.getCapabilityID("non-existent-capability", "1.0.0"); } function _getNodeOperators() internal view returns (CapabilityRegistry.NodeOperator[] memory) { diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol new file mode 100644 index 00000000000..fe85c144eea --- /dev/null +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilityRegistry} from "../CapabilityRegistry.sol"; + +contract CapabilityRegistry_AddNodesTest is BaseTest { + event NodeAdded(bytes32 p2pId, uint256 nodeOperatorId); + + uint256 private constant TEST_NODE_OPERATOR_ONE_ID = 0; + uint256 private constant TEST_NODE_OPERATOR_TWO_ID = 1; + + function setUp() public override { + BaseTest.setUp(); + changePrank(ADMIN); + s_capabilityRegistry.addNodeOperators(_getNodeOperators()); + s_capabilityRegistry.addCapability(s_basicCapability); + s_capabilityRegistry.addCapability(s_capabilityWithConfigurationContract); + } + + function test_RevertWhen_CalledByNonNodeOperatorAdmin() public { + changePrank(STRANGER); + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + + bytes32[] memory capabilityIds = new bytes32[](1); + capabilityIds[0] = s_basicCapabilityId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + supportedCapabilityIds: capabilityIds + }); + + vm.expectRevert(CapabilityRegistry.AccessForbidden.selector); + s_capabilityRegistry.addNodes(nodes); + } + + function test_RevertWhen_AddingDuplicateP2PId() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + + bytes32[] memory capabilityIds = new bytes32[](1); + capabilityIds[0] = s_basicCapabilityId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + supportedCapabilityIds: capabilityIds + }); + s_capabilityRegistry.addNodes(nodes); + + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeP2PId.selector, P2P_ID)); + s_capabilityRegistry.addNodes(nodes); + } + + function test_RevertWhen_P2PIDEmpty() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + + bytes32[] memory capabilityIds = new bytes32[](1); + capabilityIds[0] = s_basicCapabilityId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: bytes32(""), + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + supportedCapabilityIds: capabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeP2PId.selector, bytes32(""))); + s_capabilityRegistry.addNodes(nodes); + } + + function test_RevertWhen_AddingNodeWithoutCapabilities() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + + bytes32[] memory capabilityIds = new bytes32[](0); + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + supportedCapabilityIds: capabilityIds + }); + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeCapabilities.selector, capabilityIds)); + s_capabilityRegistry.addNodes(nodes); + } + + function test_RevertWhen_AddingNodeWithInvalidCapability() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + + bytes32[] memory capabilityIds = new bytes32[](1); + capabilityIds[0] = s_nonExistentCapabilityId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + supportedCapabilityIds: capabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeCapabilities.selector, capabilityIds)); + s_capabilityRegistry.addNodes(nodes); + } + + function test_AddsNode() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + bytes32[] memory capabilityIds = new bytes32[](2); + capabilityIds[0] = s_basicCapabilityId; + capabilityIds[1] = s_capabilityWithConfigurationContractId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + supportedCapabilityIds: capabilityIds + }); + + vm.expectEmit(address(s_capabilityRegistry)); + emit NodeAdded(P2P_ID, TEST_NODE_OPERATOR_ONE_ID); + s_capabilityRegistry.addNodes(nodes); + + CapabilityRegistry.Node memory node = s_capabilityRegistry.getNode(P2P_ID); + assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); + assertEq(node.p2pId, P2P_ID); + assertEq(node.supportedCapabilityIds.length, 2); + assertEq(node.supportedCapabilityIds[0], s_basicCapabilityId); + assertEq(node.supportedCapabilityIds[1], s_capabilityWithConfigurationContractId); + } +} diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_DeprecateCapability.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_DeprecateCapability.t.sol index ceefdf431cf..2e64ab7411f 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_DeprecateCapability.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_DeprecateCapability.t.sol @@ -27,10 +27,10 @@ contract CapabilityRegistry_AddCapabilityTest is BaseTest { } function test_RevertWhen_CapabilityDoesNotExist() public { - bytes32 capabilityId = s_capabilityRegistry.getCapabilityID("non-existent-capability", "1.0.0"); - - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.CapabilityDoesNotExist.selector, capabilityId)); - s_capabilityRegistry.deprecateCapability(capabilityId); + vm.expectRevert( + abi.encodeWithSelector(CapabilityRegistry.CapabilityDoesNotExist.selector, s_nonExistentCapabilityId) + ); + s_capabilityRegistry.deprecateCapability(s_nonExistentCapabilityId); } function test_RevertWhen_CapabilityAlreadyDeprecated() public { diff --git a/contracts/src/v0.8/keystone/test/Constants.t.sol b/contracts/src/v0.8/keystone/test/Constants.t.sol index 6f0b7ef43f3..0ef99f4f477 100644 --- a/contracts/src/v0.8/keystone/test/Constants.t.sol +++ b/contracts/src/v0.8/keystone/test/Constants.t.sol @@ -6,6 +6,10 @@ contract Constants { address internal STRANGER = address(2); address internal NODE_OPERATOR_ONE_ADMIN = address(3); string internal NODE_OPERATOR_ONE_NAME = "node-operator-one"; + address internal NODE_OPERATOR_ONE_SIGNER_ADDRESS = address(3333); address internal NODE_OPERATOR_TWO_ADMIN = address(4); string internal NODE_OPERATOR_TWO_NAME = "node-operator-two"; + address internal NODE_OPERATOR_TWO_SIGNER_ADDRESS = address(4444); + + bytes32 internal P2P_ID = hex"e42415859707d90ed4dc534ad730f187a17b0c368e1beec2e9b995587c4b0a05"; } diff --git a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go index 4bac3789a33..b54a101d44e 100644 --- a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go +++ b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go @@ -37,14 +37,21 @@ type CapabilityRegistryCapability struct { ConfigurationContract common.Address } +type CapabilityRegistryNode struct { + NodeOperatorId *big.Int + P2pId [32]byte + Signer common.Address + SupportedCapabilityIds [][32]byte +} + type CapabilityRegistryNodeOperator struct { Admin common.Address Name string } var CapabilityRegistryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAlreadyDeprecated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"lengthOne\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lengthTwo\",\"type\":\"uint256\"}],\"name\":\"LengthMismatch\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDeprecated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"deprecateCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilities\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityID\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"isCapabilityDeprecated\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"updateNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611a7d80620001586000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c806365c14dc71161008c5780639cb7c5f4116100665780639cb7c5f41461023c578063ae3c241c1461025c578063ddbe4f821461026f578063f2fde38b1461028457600080fd5b806365c14dc7146101ec57806379ba50971461020c5780638da5cb5b1461021457600080fd5b8063181f5a77116100c8578063181f5a771461013f5780631cdf63431461017e578063229111f514610191578063398f3773146101d957600080fd5b80630c5801e3146100ef578063117392ce146101045780631257001114610117575b600080fd5b6101026100fd36600461120e565b610297565b005b61010261011236600461127a565b6105a8565b61012a610125366004611292565b6107f3565b60405190151581526020015b60405180910390f35b604080518082018252601881527f4361706162696c697479526567697374727920312e302e30000000000000000060208201529051610136919061130f565b61010261018c366004611322565b610806565b6101cb61019f366004611364565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b604051908152602001610136565b6101026101e7366004611322565b6108c9565b6101ff6101fa366004611292565b610a62565b6040516101369190611386565b610102610b48565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610136565b61024f61024a366004611292565b610c45565b6040516101369190611468565b61010261026a366004611292565b610cef565b610277610dba565b6040516101369190611476565b6101026102923660046114e6565b610eff565b8281146102df576040517fab8b67c600000000000000000000000000000000000000000000000000000000815260048101849052602481018290526044015b60405180910390fd5b6000805473ffffffffffffffffffffffffffffffffffffffff16905b848110156105a057600086868381811061031757610317611503565b905060200201359050600085858481811061033457610334611503565b90506020028101906103469190611532565b61034f90611617565b805190915073ffffffffffffffffffffffffffffffffffffffff166103a0576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff1633148015906103dd57503373ffffffffffffffffffffffffffffffffffffffff851614155b15610414576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160008381526007602052604090205473ffffffffffffffffffffffffffffffffffffffff90811691161415806104c6575060208082015160405161045a920161130f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206000868152600783529290922091926104ad926001019101611730565b6040516020818303038152906040528051906020012014155b1561058d578051600083815260076020908152604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909316929092178255820151600190910190610533908261181f565b50806000015173ffffffffffffffffffffffffffffffffffffffff167f14c8f513e8a6d86d2d16b0cb64976de4e72386c4f8068eca3b7354373f8fe97a838360200151604051610584929190611939565b60405180910390a25b50508061059990611981565b90506102fb565b505050505050565b6105b0610f13565b6040805182356020828101919091528084013582840152825180830384018152606090920190925280519101206105e8600382610f96565b1561061f576040517fe288638f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061063160808401606085016114e6565b73ffffffffffffffffffffffffffffffffffffffff161461079c5761065c60808301606084016114e6565b73ffffffffffffffffffffffffffffffffffffffff163b158061073c575061068a60808301606084016114e6565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f884efe6100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff91909116906301ffc9a790602401602060405180830381865afa158015610716573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073a91906119b9565b155b1561079c5761075160808301606084016114e6565b6040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016102d6565b6107a7600382610fb1565b50600081815260026020526040902082906107c282826119db565b505060405181907f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff0690600090a25050565b6000610800600583610f96565b92915050565b61080e610f13565b60005b818110156108c457600083838381811061082d5761082d611503565b60209081029290920135600081815260079093526040832080547fffffffffffffffffffffffff000000000000000000000000000000000000000016815590935091905061087e6001830182611174565b50506040518181527f1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f9060200160405180910390a1506108bd81611981565b9050610811565b505050565b6108d1610f13565b60005b818110156108c45760008383838181106108f0576108f0611503565b90506020028101906109029190611532565b61090b90611617565b805190915073ffffffffffffffffffffffffffffffffffffffff1661095c576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600854604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526007909252939020825181547fffffffffffffffffffffffff0000000000000000000000000000000000000000169216919091178155915190919060018201906109df908261181f565b509050506008600081546109f290611981565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b91610a4791859190611939565b60405180910390a2505080610a5b90611981565b90506108d4565b6040805180820190915260008152606060208201526000828152600760209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610abf906116e3565b80601f0160208091040260200160405190810160405280929190818152602001828054610aeb906116e3565b8015610b385780601f10610b0d57610100808354040283529160200191610b38565b820191906000526020600020905b815481529060010190602001808311610b1b57829003601f168201915b5050505050815250509050919050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610bc9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016102d6565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b604080516080808201835260008083526020808401829052838501829052606084018290528582526002808252918590208551938401865280548452600180820154928501929092529182015493949293919284019160ff1690811115610cae57610cae6113c9565b6001811115610cbf57610cbf6113c9565b815260029190910154610100900473ffffffffffffffffffffffffffffffffffffffff1660209091015292915050565b610cf7610f13565b610d02600382610f96565b610d3b576040517fe181733f000000000000000000000000000000000000000000000000000000008152600481018290526024016102d6565b610d46600582610f96565b15610d80576040517f16950d1d000000000000000000000000000000000000000000000000000000008152600481018290526024016102d6565b610d8b600582610fb1565b5060405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf2190600090a250565b60606000610dc86003610fbd565b90506000610dd66005610fca565b8251610de29190611a5d565b67ffffffffffffffff811115610dfa57610dfa611570565b604051908082528060200260200182016040528015610e6a57816020015b6040805160808101825260008082526020808301829052928201819052606082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181610e185790505b5090506000805b8351811015610ef6576000848281518110610e8e57610e8e611503565b60200260200101519050610eac816005610f9690919063ffffffff16565b610ee557610eb981610c45565b848481518110610ecb57610ecb611503565b60200260200101819052508280610ee190611981565b9350505b50610eef81611981565b9050610e71565b50909392505050565b610f07610f13565b610f1081610fd4565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610f94576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016102d6565b565b600081815260018301602052604081205415155b9392505050565b6000610faa83836110c9565b60606000610faa83611118565b6000610800825490565b3373ffffffffffffffffffffffffffffffffffffffff821603611053576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016102d6565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600081815260018301602052604081205461111057508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610800565b506000610800565b60608160000180548060200260200160405190810160405280929190818152602001828054801561116857602002820191906000526020600020905b815481526020019060010190808311611154575b50505050509050919050565b508054611180906116e3565b6000825580601f10611190575050565b601f016020900490600052602060002090810190610f1091905b808211156111be57600081556001016111aa565b5090565b60008083601f8401126111d457600080fd5b50813567ffffffffffffffff8111156111ec57600080fd5b6020830191508360208260051b850101111561120757600080fd5b9250929050565b6000806000806040858703121561122457600080fd5b843567ffffffffffffffff8082111561123c57600080fd5b611248888389016111c2565b9096509450602087013591508082111561126157600080fd5b5061126e878288016111c2565b95989497509550505050565b60006080828403121561128c57600080fd5b50919050565b6000602082840312156112a457600080fd5b5035919050565b6000815180845260005b818110156112d1576020818501810151868301820152016112b5565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610faa60208301846112ab565b6000806020838503121561133557600080fd5b823567ffffffffffffffff81111561134c57600080fd5b611358858286016111c2565b90969095509350505050565b6000806040838503121561137757600080fd5b50508035926020909101359150565b6020815273ffffffffffffffffffffffffffffffffffffffff8251166020820152600060208301516040808401526113c160608401826112ab565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8051825260208101516020830152604081015160028110611442577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b604083015260609081015173ffffffffffffffffffffffffffffffffffffffff16910152565b6080810161080082846113f8565b6020808252825182820181905260009190848201906040850190845b818110156114b8576114a58385516113f8565b9284019260809290920191600101611492565b50909695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f1057600080fd5b6000602082840312156114f857600080fd5b8135610faa816114c4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261156657600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156115c2576115c2611570565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561160f5761160f611570565b604052919050565b60006040823603121561162957600080fd5b61163161159f565b823561163c816114c4565b815260208381013567ffffffffffffffff8082111561165a57600080fd5b9085019036601f83011261166d57600080fd5b81358181111561167f5761167f611570565b6116af847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016115c8565b915080825236848285010111156116c557600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c908216806116f757607f821691505b60208210810361128c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454611744816116e3565b80848701526040600180841660008114611765576001811461179d576117cb565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a010195506117cb565b896000528660002060005b858110156117c35781548b82018601529083019088016117a8565b8a0184019650505b509398975050505050505050565b601f8211156108c457600081815260208120601f850160051c810160208610156118005750805b601f850160051c820191505b818110156105a05782815560010161180c565b815167ffffffffffffffff81111561183957611839611570565b61184d8161184784546116e3565b846117d9565b602080601f8311600181146118a0576000841561186a5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556105a0565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156118ed578886015182559484019460019091019084016118ce565b508582101561192957878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8281526040602082015260006113c160408301846112ab565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036119b2576119b2611952565b5060010190565b6000602082840312156119cb57600080fd5b81518015158114610faa57600080fd5b8135815560208201356001820155600281016040830135600281106119ff57600080fd5b81546060850135611a0f816114c4565b74ffffffffffffffffffffffffffffffffffffffff008160081b1660ff84167fffffffffffffffffffffff000000000000000000000000000000000000000000841617178455505050505050565b818103818111156108005761080061195256fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAlreadyDeprecated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"capabilityIds\",\"type\":\"bytes32[]\"}],\"name\":\"InvalidNodeCapabilities\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"InvalidNodeP2PId\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"lengthOne\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lengthTwo\",\"type\":\"uint256\"}],\"name\":\"LengthMismatch\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDeprecated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"addNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"deprecateCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilities\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityID\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"getNode\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"isCapabilityDeprecated\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"updateNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60806040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000a5565b50505062000150565b336001600160a01b03821603620000ff5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61214580620001606000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c806365c14dc711610097578063ae3c241c11610066578063ae3c241c14610292578063c2d483a1146102a5578063ddbe4f82146102b8578063f2fde38b146102cd57600080fd5b806365c14dc71461022257806379ba5097146102425780638da5cb5b1461024a5780639cb7c5f41461027257600080fd5b80631cdf6343116100d35780631cdf634314610194578063229111f5146101a7578063398f3773146101ef57806350c946fe1461020257600080fd5b80630c5801e314610105578063117392ce1461011a578063125700111461012d578063181f5a7714610155575b600080fd5b6101186101133660046116ec565b6102e0565b005b610118610128366004611758565b6105f1565b61014061013b366004611770565b61083c565b60405190151581526020015b60405180910390f35b604080518082018252601881527f4361706162696c697479526567697374727920312e302e3000000000000000006020820152905161014c91906117ed565b6101186101a2366004611800565b61084f565b6101e16101b5366004611842565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b60405190815260200161014c565b6101186101fd366004611800565b610912565b610215610210366004611770565b610aab565b60405161014c9190611864565b610235610230366004611770565b610b73565b60405161014c91906118ea565b610118610c50565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b610285610280366004611770565b610d4d565b60405161014c91906119cc565b6101186102a0366004611770565b610df7565b6101186102b3366004611800565b610ec2565b6102c061124c565b60405161014c91906119da565b6101186102db366004611a4a565b611391565b828114610328576040517fab8b67c600000000000000000000000000000000000000000000000000000000815260048101849052602481018290526044015b60405180910390fd5b6000805473ffffffffffffffffffffffffffffffffffffffff16905b848110156105e957600086868381811061036057610360611a67565b905060200201359050600085858481811061037d5761037d611a67565b905060200281019061038f9190611a96565b61039890611b9e565b805190915073ffffffffffffffffffffffffffffffffffffffff166103e9576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16331480159061042657503373ffffffffffffffffffffffffffffffffffffffff851614155b1561045d576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160008381526007602052604090205473ffffffffffffffffffffffffffffffffffffffff908116911614158061050f57506020808201516040516104a392016117ed565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206000868152600783529290922091926104f6926001019101611cb7565b6040516020818303038152906040528051906020012014155b156105d6578051600083815260076020908152604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90931692909217825582015160019091019061057c9082611da6565b50806000015173ffffffffffffffffffffffffffffffffffffffff167f14c8f513e8a6d86d2d16b0cb64976de4e72386c4f8068eca3b7354373f8fe97a8383602001516040516105cd929190611ec0565b60405180910390a25b5050806105e290611f08565b9050610344565b505050505050565b6105f96113a5565b604080518235602082810191909152808401358284015282518083038401815260609092019092528051910120610631600382611428565b15610668576040517fe288638f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061067a6080840160608501611a4a565b73ffffffffffffffffffffffffffffffffffffffff16146107e5576106a56080830160608401611a4a565b73ffffffffffffffffffffffffffffffffffffffff163b158061078557506106d36080830160608401611a4a565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f884efe6100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff91909116906301ffc9a790602401602060405180830381865afa15801561075f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107839190611f40565b155b156107e55761079a6080830160608401611a4a565b6040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161031f565b6107f0600382611443565b506000818152600260205260409020829061080b8282611f62565b505060405181907f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff0690600090a25050565b6000610849600583611428565b92915050565b6108576113a5565b60005b8181101561090d57600083838381811061087657610876611a67565b60209081029290920135600081815260079093526040832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559093509190506108c76001830182611606565b50506040518181527f1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f9060200160405180910390a15061090681611f08565b905061085a565b505050565b61091a6113a5565b60005b8181101561090d57600083838381811061093957610939611a67565b905060200281019061094b9190611a96565b61095490611b9e565b805190915073ffffffffffffffffffffffffffffffffffffffff166109a5576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600954604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526007909252939020825181547fffffffffffffffffffffffff000000000000000000000000000000000000000016921691909117815591519091906001820190610a289082611da6565b50905050600960008154610a3b90611f08565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b91610a9091859190611ec0565b60405180910390a2505080610aa490611f08565b905061091d565b6040805160808101825260008082526020820181905291810191909152606080820152600082815260086020908152604091829020825160808101845281548152600182015481840152600282015473ffffffffffffffffffffffffffffffffffffffff16818501526003820180548551818602810186019096528086529194929360608601939290830182828015610b6357602002820191906000526020600020905b815481526020019060010190808311610b4f575b5050505050815250509050919050565b6040805180820190915260008152606060208201526000828152600760209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610bd090611c6a565b80601f0160208091040260200160405190810160405280929190818152602001828054610bfc90611c6a565b8015610b635780601f10610c1e57610100808354040283529160200191610b63565b820191906000526020600020905b815481529060010190602001808311610c2c57505050919092525091949350505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610cd1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161031f565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b604080516080808201835260008083526020808401829052838501829052606084018290528582526002808252918590208551938401865280548452600180820154928501929092529182015493949293919284019160ff1690811115610db657610db661192d565b6001811115610dc757610dc761192d565b815260029190910154610100900473ffffffffffffffffffffffffffffffffffffffff1660209091015292915050565b610dff6113a5565b610e0a600382611428565b610e43576040517fe181733f0000000000000000000000000000000000000000000000000000000081526004810182905260240161031f565b610e4e600582611428565b15610e88576040517f16950d1d0000000000000000000000000000000000000000000000000000000081526004810182905260240161031f565b610e93600582611443565b5060405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf2190600090a250565b60005b8181101561090d576000838383818110610ee157610ee1611a67565b9050602002810190610ef39190611fe4565b610efc90612018565b805160009081526007602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff168252600181018054959650939491939092840191610f4c90611c6a565b80601f0160208091040260200160405190810160405280929190818152602001828054610f7890611c6a565b8015610fc55780601f10610f9a57610100808354040283529160200191610fc5565b820191906000526020600020905b815481529060010190602001808311610fa857829003601f168201915b5050505050815250509050806000015173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611039576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020808301516000908152600890915260409020600301541515808061106157506020830151155b156110a05782602001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161031f91815260200190565b8260600151516000036110e55782606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161031f91906120ed565b60005b836060015151811015611172576111268460600151828151811061110e5761110e611a67565b6020026020010151600361142890919063ffffffff16565b6111625783606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161031f91906120ed565b61116b81611f08565b90506110e8565b506020838101805160009081526008835260409081902086518155915160018301558501516002820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9092169190911790556060850151805186936111f7926003850192910190611640565b505050602083810151845160408051928352928201527f5bfe8a52ad26ac6ee7b0cd46d2fd92be04735a31c45ef8aa3d4b7ea1b61bbc1f910160405180910390a15050508061124590611f08565b9050610ec5565b6060600061125a600361144f565b90506000611268600561145c565b82516112749190612125565b67ffffffffffffffff81111561128c5761128c611ad4565b6040519080825280602002602001820160405280156112fc57816020015b6040805160808101825260008082526020808301829052928201819052606082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816112aa5790505b5090506000805b835181101561138857600084828151811061132057611320611a67565b6020026020010151905061133e81600561142890919063ffffffff16565b6113775761134b81610d4d565b84848151811061135d5761135d611a67565b6020026020010181905250828061137390611f08565b9350505b5061138181611f08565b9050611303565b50909392505050565b6113996113a5565b6113a281611466565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314611426576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161031f565b565b600081815260018301602052604081205415155b9392505050565b600061143c838361155b565b6060600061143c836115aa565b6000610849825490565b3373ffffffffffffffffffffffffffffffffffffffff8216036114e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161031f565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120546115a257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610849565b506000610849565b6060816000018054806020026020016040519081016040528092919081815260200182805480156115fa57602002820191906000526020600020905b8154815260200190600101908083116115e6575b50505050509050919050565b50805461161290611c6a565b6000825580601f10611622575050565b601f0160209004906000526020600020908101906113a2919061168b565b82805482825590600052602060002090810192821561167b579160200282015b8281111561167b578251825591602001919060010190611660565b5061168792915061168b565b5090565b5b80821115611687576000815560010161168c565b60008083601f8401126116b257600080fd5b50813567ffffffffffffffff8111156116ca57600080fd5b6020830191508360208260051b85010111156116e557600080fd5b9250929050565b6000806000806040858703121561170257600080fd5b843567ffffffffffffffff8082111561171a57600080fd5b611726888389016116a0565b9096509450602087013591508082111561173f57600080fd5b5061174c878288016116a0565b95989497509550505050565b60006080828403121561176a57600080fd5b50919050565b60006020828403121561178257600080fd5b5035919050565b6000815180845260005b818110156117af57602081850181015186830182015201611793565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061143c6020830184611789565b6000806020838503121561181357600080fd5b823567ffffffffffffffff81111561182a57600080fd5b611836858286016116a0565b90969095509350505050565b6000806040838503121561185557600080fd5b50508035926020909101359150565b6000602080835260a0830184518285015281850151604085015273ffffffffffffffffffffffffffffffffffffffff6040860151166060850152606085015160808086015281815180845260c0870191508483019350600092505b808310156118df57835182529284019260019290920191908401906118bf565b509695505050505050565b6020815273ffffffffffffffffffffffffffffffffffffffff8251166020820152600060208301516040808401526119256060840182611789565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b80518252602081015160208301526040810151600281106119a6577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b604083015260609081015173ffffffffffffffffffffffffffffffffffffffff16910152565b60808101610849828461195c565b6020808252825182820181905260009190848201906040850190845b81811015611a1c57611a0983855161195c565b92840192608092909201916001016119f6565b50909695505050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146113a257600080fd5b600060208284031215611a5c57600080fd5b813561143c81611a28565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112611aca57600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611b2657611b26611ad4565b60405290565b6040516080810167ffffffffffffffff81118282101715611b2657611b26611ad4565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611b9657611b96611ad4565b604052919050565b600060408236031215611bb057600080fd5b611bb8611b03565b8235611bc381611a28565b815260208381013567ffffffffffffffff80821115611be157600080fd5b9085019036601f830112611bf457600080fd5b813581811115611c0657611c06611ad4565b611c36847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611b4f565b91508082523684828501011115611c4c57600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c90821680611c7e57607f821691505b60208210810361176a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454611ccb81611c6a565b80848701526040600180841660008114611cec5760018114611d2457611d52565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a01019550611d52565b896000528660002060005b85811015611d4a5781548b8201860152908301908801611d2f565b8a0184019650505b509398975050505050505050565b601f82111561090d57600081815260208120601f850160051c81016020861015611d875750805b601f850160051c820191505b818110156105e957828155600101611d93565b815167ffffffffffffffff811115611dc057611dc0611ad4565b611dd481611dce8454611c6a565b84611d60565b602080601f831160018114611e275760008415611df15750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556105e9565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015611e7457888601518255948401946001909101908401611e55565b5085821015611eb057878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8281526040602082015260006119256040830184611789565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611f3957611f39611ed9565b5060010190565b600060208284031215611f5257600080fd5b8151801515811461143c57600080fd5b813581556020820135600182015560028101604083013560028110611f8657600080fd5b81546060850135611f9681611a28565b74ffffffffffffffffffffffffffffffffffffffff008160081b1660ff84167fffffffffffffffffffffff000000000000000000000000000000000000000000841617178455505050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112611aca57600080fd5b60006080823603121561202a57600080fd5b612032611b2c565b8235815260208084013581830152604084013561204e81611a28565b6040830152606084013567ffffffffffffffff8082111561206e57600080fd5b9085019036601f83011261208157600080fd5b81358181111561209357612093611ad4565b8060051b91506120a4848301611b4f565b81815291830184019184810190368411156120be57600080fd5b938501935b838510156120dc578435825293850193908501906120c3565b606087015250939695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015611a1c57835183529284019291840191600101612109565b8181038181111561084957610849611ed956fea164736f6c6343000813000a", } var CapabilityRegistryABI = CapabilityRegistryMetaData.ABI @@ -249,6 +256,28 @@ func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapabilityID(capa return _CapabilityRegistry.Contract.GetCapabilityID(&_CapabilityRegistry.CallOpts, capabilityType, version) } +func (_CapabilityRegistry *CapabilityRegistryCaller) GetNode(opts *bind.CallOpts, p2pId [32]byte) (CapabilityRegistryNode, error) { + var out []interface{} + err := _CapabilityRegistry.contract.Call(opts, &out, "getNode", p2pId) + + if err != nil { + return *new(CapabilityRegistryNode), err + } + + out0 := *abi.ConvertType(out[0], new(CapabilityRegistryNode)).(*CapabilityRegistryNode) + + return out0, err + +} + +func (_CapabilityRegistry *CapabilityRegistrySession) GetNode(p2pId [32]byte) (CapabilityRegistryNode, error) { + return _CapabilityRegistry.Contract.GetNode(&_CapabilityRegistry.CallOpts, p2pId) +} + +func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetNode(p2pId [32]byte) (CapabilityRegistryNode, error) { + return _CapabilityRegistry.Contract.GetNode(&_CapabilityRegistry.CallOpts, p2pId) +} + func (_CapabilityRegistry *CapabilityRegistryCaller) GetNodeOperator(opts *bind.CallOpts, nodeOperatorId *big.Int) (CapabilityRegistryNodeOperator, error) { var out []interface{} err := _CapabilityRegistry.contract.Call(opts, &out, "getNodeOperator", nodeOperatorId) @@ -373,6 +402,18 @@ func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AddNodeOperators return _CapabilityRegistry.Contract.AddNodeOperators(&_CapabilityRegistry.TransactOpts, nodeOperators) } +func (_CapabilityRegistry *CapabilityRegistryTransactor) AddNodes(opts *bind.TransactOpts, nodes []CapabilityRegistryNode) (*types.Transaction, error) { + return _CapabilityRegistry.contract.Transact(opts, "addNodes", nodes) +} + +func (_CapabilityRegistry *CapabilityRegistrySession) AddNodes(nodes []CapabilityRegistryNode) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.AddNodes(&_CapabilityRegistry.TransactOpts, nodes) +} + +func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AddNodes(nodes []CapabilityRegistryNode) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.AddNodes(&_CapabilityRegistry.TransactOpts, nodes) +} + func (_CapabilityRegistry *CapabilityRegistryTransactor) DeprecateCapability(opts *bind.TransactOpts, capabilityId [32]byte) (*types.Transaction, error) { return _CapabilityRegistry.contract.Transact(opts, "deprecateCapability", capabilityId) } @@ -675,6 +716,124 @@ func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseCapabilityDeprecated return event, nil } +type CapabilityRegistryNodeAddedIterator struct { + Event *CapabilityRegistryNodeAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilityRegistryNodeAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryNodeAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryNodeAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CapabilityRegistryNodeAddedIterator) Error() error { + return it.fail +} + +func (it *CapabilityRegistryNodeAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilityRegistryNodeAdded struct { + P2pId [32]byte + NodeOperatorId *big.Int + Raw types.Log +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterNodeAdded(opts *bind.FilterOpts) (*CapabilityRegistryNodeAddedIterator, error) { + + logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "NodeAdded") + if err != nil { + return nil, err + } + return &CapabilityRegistryNodeAddedIterator{contract: _CapabilityRegistry.contract, event: "NodeAdded", logs: logs, sub: sub}, nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchNodeAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeAdded) (event.Subscription, error) { + + logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "NodeAdded") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilityRegistryNodeAdded) + if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeAdded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseNodeAdded(log types.Log) (*CapabilityRegistryNodeAdded, error) { + event := new(CapabilityRegistryNodeAdded) + if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type CapabilityRegistryNodeOperatorAddedIterator struct { Event *CapabilityRegistryNodeOperatorAdded @@ -1328,6 +1487,8 @@ func (_CapabilityRegistry *CapabilityRegistry) ParseLog(log types.Log) (generate return _CapabilityRegistry.ParseCapabilityAdded(log) case _CapabilityRegistry.abi.Events["CapabilityDeprecated"].ID: return _CapabilityRegistry.ParseCapabilityDeprecated(log) + case _CapabilityRegistry.abi.Events["NodeAdded"].ID: + return _CapabilityRegistry.ParseNodeAdded(log) case _CapabilityRegistry.abi.Events["NodeOperatorAdded"].ID: return _CapabilityRegistry.ParseNodeOperatorAdded(log) case _CapabilityRegistry.abi.Events["NodeOperatorRemoved"].ID: @@ -1352,6 +1513,10 @@ func (CapabilityRegistryCapabilityDeprecated) Topic() common.Hash { return common.HexToHash("0xdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf21") } +func (CapabilityRegistryNodeAdded) Topic() common.Hash { + return common.HexToHash("0x5bfe8a52ad26ac6ee7b0cd46d2fd92be04735a31c45ef8aa3d4b7ea1b61bbc1f") +} + func (CapabilityRegistryNodeOperatorAdded) Topic() common.Hash { return common.HexToHash("0xda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b") } @@ -1383,6 +1548,8 @@ type CapabilityRegistryInterface interface { GetCapabilityID(opts *bind.CallOpts, capabilityType [32]byte, version [32]byte) ([32]byte, error) + GetNode(opts *bind.CallOpts, p2pId [32]byte) (CapabilityRegistryNode, error) + GetNodeOperator(opts *bind.CallOpts, nodeOperatorId *big.Int) (CapabilityRegistryNodeOperator, error) IsCapabilityDeprecated(opts *bind.CallOpts, capabilityId [32]byte) (bool, error) @@ -1397,6 +1564,8 @@ type CapabilityRegistryInterface interface { AddNodeOperators(opts *bind.TransactOpts, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) + AddNodes(opts *bind.TransactOpts, nodes []CapabilityRegistryNode) (*types.Transaction, error) + DeprecateCapability(opts *bind.TransactOpts, capabilityId [32]byte) (*types.Transaction, error) RemoveNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []*big.Int) (*types.Transaction, error) @@ -1417,6 +1586,12 @@ type CapabilityRegistryInterface interface { ParseCapabilityDeprecated(log types.Log) (*CapabilityRegistryCapabilityDeprecated, error) + FilterNodeAdded(opts *bind.FilterOpts) (*CapabilityRegistryNodeAddedIterator, error) + + WatchNodeAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeAdded) (event.Subscription, error) + + ParseNodeAdded(log types.Log) (*CapabilityRegistryNodeAdded, error) + FilterNodeOperatorAdded(opts *bind.FilterOpts, admin []common.Address) (*CapabilityRegistryNodeOperatorAddedIterator, error) WatchNodeOperatorAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeOperatorAdded, admin []common.Address) (event.Subscription, error) diff --git a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 0dff3f2986e..3e0110cdee6 100644 --- a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,4 +1,4 @@ GETH_VERSION: 1.13.8 forwarder: ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.bin b4c900aae9e022f01abbac7993d41f93912247613ac6270b0c4da4ef6f2016e3 -keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin 28fb0e1c437b97271d999f3b028f7bd44558352ec83f89501aabf501fcc915f1 +keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin b7d748b585d7cf1cf91e268b609613f77a8390d119e03d724b49c25fd2ea75e7 ocr3_capability: ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.bin 9dcbdf55bd5729ba266148da3f17733eb592c871c2108ccca546618628fd9ad2 From ded90f0837c9726ae1ffb86caa63af456d8451b4 Mon Sep 17 00:00:00 2001 From: Cedric Date: Wed, 1 May 2024 18:59:11 +0100 Subject: [PATCH 23/45] [chore] Introduce test hooks (#13066) --- core/services/workflows/engine.go | 34 ++++++++++++-------------- core/services/workflows/engine_test.go | 34 +++++++++++++++++--------- 2 files changed, 38 insertions(+), 30 deletions(-) diff --git a/core/services/workflows/engine.go b/core/services/workflows/engine.go index 040e123567e..9629e845336 100644 --- a/core/services/workflows/engine.go +++ b/core/services/workflows/engine.go @@ -43,8 +43,8 @@ type Engine struct { stopCh services.StopChan newWorkerTimeout time.Duration - // Used for testing to wait for an execution to complete - xxxExecutionFinished chan string + // testing lifecycle hook to signal when an execution is finished. + onExecutionFinished func(string) // testing lifecycle hook to signal initialization status afterInit func(success bool) // Used for testing to control the number of retries @@ -511,14 +511,7 @@ func (e *Engine) finishExecution(ctx context.Context, executionID string, status return err } - // Signal that an execution has finished in a - // non-blocking fashion. This is intended for - // testing purposes only. - select { - case e.xxxExecutionFinished <- executionID: - default: - } - + e.onExecutionFinished(executionID) return nil } @@ -688,9 +681,10 @@ type Config struct { PeerID func() *p2ptypes.PeerID // For testing purposes only - maxRetries int - retryMs int - afterInit func(success bool) + maxRetries int + retryMs int + afterInit func(success bool) + onExecutionFinished func(weid string) } const ( @@ -720,6 +714,10 @@ func NewEngine(cfg Config) (engine *Engine, err error) { cfg.afterInit = func(success bool) {} } + if cfg.onExecutionFinished == nil { + cfg.onExecutionFinished = func(weid string) {} + } + // TODO: validation of the workflow spec // We'll need to check, among other things: // - that there are no step `ref` called `trigger` as this is reserved for any triggers @@ -756,11 +754,11 @@ func NewEngine(cfg Config) (engine *Engine, err error) { triggerEvents: make(chan capabilities.CapabilityResponse), stopCh: make(chan struct{}), newWorkerTimeout: cfg.NewWorkerTimeout, - // For testing purposes only - xxxExecutionFinished: make(chan string), - afterInit: cfg.afterInit, - maxRetries: cfg.maxRetries, - retryMs: cfg.retryMs, + + onExecutionFinished: cfg.onExecutionFinished, + afterInit: cfg.afterInit, + maxRetries: cfg.maxRetries, + retryMs: cfg.retryMs, } return engine, nil } diff --git a/core/services/workflows/engine_test.go b/core/services/workflows/engine_test.go index 4821b5800c7..3896f840ee8 100644 --- a/core/services/workflows/engine_test.go +++ b/core/services/workflows/engine_test.go @@ -65,10 +65,16 @@ targets: abi: "receive(report bytes)" ` +type testHooks struct { + initFailed chan struct{} + executionFinished chan string +} + // newTestEngine creates a new engine with some test defaults. -func newTestEngine(t *testing.T, reg *coreCap.Registry, spec string) (eng *Engine, initFailed chan struct{}) { +func newTestEngine(t *testing.T, reg *coreCap.Registry, spec string) (*Engine, *testHooks) { peerID := p2ptypes.PeerID{} - initFailed = make(chan struct{}) + initFailed := make(chan struct{}) + executionFinished := make(chan string, 100) cfg := Config{ Lggr: logger.TestLogger(t), Registry: reg, @@ -82,10 +88,13 @@ func newTestEngine(t *testing.T, reg *coreCap.Registry, spec string) (eng *Engin close(initFailed) } }, + onExecutionFinished: func(weid string) { + executionFinished <- weid + }, } eng, err := NewEngine(cfg) require.NoError(t, err) - return eng, initFailed + return eng, &testHooks{initFailed: initFailed, executionFinished: executionFinished} } // getExecutionId returns the execution id of the workflow that is @@ -93,13 +102,14 @@ func newTestEngine(t *testing.T, reg *coreCap.Registry, spec string) (eng *Engin // // If the engine fails to initialize, the test will fail rather // than blocking indefinitely. -func getExecutionId(t *testing.T, eng *Engine, initFailed <-chan struct{}) string { +func getExecutionId(t *testing.T, eng *Engine, hooks *testHooks) string { var eid string select { - case <-initFailed: + case <-hooks.initFailed: t.FailNow() - case eid = <-eng.xxxExecutionFinished: + case eid = <-hooks.executionFinished: } + return eid } @@ -186,13 +196,13 @@ func TestEngineWithHardcodedWorkflow(t *testing.T) { ) require.NoError(t, reg.Add(ctx, target2)) - eng, initFailed := newTestEngine(t, reg, hardcodedWorkflow) + eng, hooks := newTestEngine(t, reg, hardcodedWorkflow) err := eng.Start(ctx) require.NoError(t, err) defer eng.Close() - eid := getExecutionId(t, eng, initFailed) + eid := getExecutionId(t, eng, hooks) assert.Equal(t, cr, <-target1.response) assert.Equal(t, cr, <-target2.response) @@ -340,13 +350,13 @@ func TestEngine_ErrorsTheWorkflowIfAStepErrors(t *testing.T) { require.NoError(t, reg.Add(ctx, mockFailingConsensus())) require.NoError(t, reg.Add(ctx, mockTarget())) - eng, initFailed := newTestEngine(t, reg, simpleWorkflow) + eng, hooks := newTestEngine(t, reg, simpleWorkflow) err := eng.Start(ctx) require.NoError(t, err) defer eng.Close() - eid := getExecutionId(t, eng, initFailed) + eid := getExecutionId(t, eng, hooks) state, err := eng.executionStates.get(ctx, eid) require.NoError(t, err) @@ -439,12 +449,12 @@ func TestEngine_MultiStepDependencies(t *testing.T) { action, out := mockAction() require.NoError(t, reg.Add(ctx, action)) - eng, initFailed := newTestEngine(t, reg, multiStepWorkflow) + eng, hooks := newTestEngine(t, reg, multiStepWorkflow) err := eng.Start(ctx) require.NoError(t, err) defer eng.Close() - eid := getExecutionId(t, eng, initFailed) + eid := getExecutionId(t, eng, hooks) state, err := eng.executionStates.get(ctx, eid) require.NoError(t, err) From 3f065cfcf4ea0e67edfc46082115f4d882c18459 Mon Sep 17 00:00:00 2001 From: Sneha Agnihotri <180277+snehaagni@users.noreply.github.com> Date: Wed, 1 May 2024 11:56:14 -0700 Subject: [PATCH 24/45] chore/release 2.11.0 to develop (#13067) * Bump version and update CHANGELOG for core 2.11.0 Signed-off-by: Sneha Agnihotri * Add jfpc cache staleness alert to config and pass it into jfpc cache (#12595) * Add jfpc cache staleness alert to config and pass it into jfpc cache * Extract JuelsPerFeeCoinCache cfg into a separate struct, improve naming * Changeset * Update config validation test * Reduce changeset to minor * [BCF-3178] - Improve err handling and logs for in memory data source cache (#12907) * Fix inMemoryDataSourceCache get() warn log formatting * Fix in mem ds cache updateCache() to save runs even if some ds failed * Improve in memory data source cache Observe() logs and error messages * Add changeset * Bumping solana validator (#12832) * Bumping solana * Bumping the checksum for solana validator * Update release changelog with cherry pick commits from develop Signed-off-by: Sneha Agnihotri * Cherry pick: enable jpfc cache by default (#12973) * Draft * Check JuelsPerFeeCoinCache before checking Disable param * Add test * Update NewInMemoryDataSourceCache * Update NewInMemoryDataSourceCache * Update release changelog with cherry pick commits from develop Signed-off-by: Sneha Agnihotri * Remove duplicates Signed-off-by: Sneha Agnihotri * Finalize date on changelog for 2.11.0 Signed-off-by: Sneha Agnihotri * Remove codecov (#13020) (cherry picked from commit 2e994684de6d326ff3dc4674986a10fbf28e3511) --------- Signed-off-by: Sneha Agnihotri Co-authored-by: ilija42 <57732589+ilija42@users.noreply.github.com> Co-authored-by: Damjan Smickovski <32773226+smickovskid@users.noreply.github.com> Co-authored-by: george-dorin <120329946+george-dorin@users.noreply.github.com> Co-authored-by: HenryNguyen5 <6404866+HenryNguyen5@users.noreply.github.com> --- .changeset/beige-papayas-develop.md | 5 ----- .changeset/early-cats-check.md | 5 ----- .changeset/loud-peaches-beg.md | 5 ----- .changeset/odd-horses-fix.md | 5 ----- .changeset/sour-needles-collect.md | 5 ----- .changeset/ten-clouds-collect.md | 5 ----- CHANGELOG.md | 32 +++++++++++++++-------------- 7 files changed, 17 insertions(+), 45 deletions(-) delete mode 100644 .changeset/beige-papayas-develop.md delete mode 100644 .changeset/early-cats-check.md delete mode 100644 .changeset/loud-peaches-beg.md delete mode 100644 .changeset/odd-horses-fix.md delete mode 100644 .changeset/sour-needles-collect.md delete mode 100644 .changeset/ten-clouds-collect.md diff --git a/.changeset/beige-papayas-develop.md b/.changeset/beige-papayas-develop.md deleted file mode 100644 index 0408383bd03..00000000000 --- a/.changeset/beige-papayas-develop.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal diff --git a/.changeset/early-cats-check.md b/.changeset/early-cats-check.md deleted file mode 100644 index 0408383bd03..00000000000 --- a/.changeset/early-cats-check.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal diff --git a/.changeset/loud-peaches-beg.md b/.changeset/loud-peaches-beg.md deleted file mode 100644 index cd880ae5f5c..00000000000 --- a/.changeset/loud-peaches-beg.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -support decimals #added diff --git a/.changeset/odd-horses-fix.md b/.changeset/odd-horses-fix.md deleted file mode 100644 index 290d82bebfe..00000000000 --- a/.changeset/odd-horses-fix.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -contracts work diff --git a/.changeset/sour-needles-collect.md b/.changeset/sour-needles-collect.md deleted file mode 100644 index 5d1ae86fd7c..00000000000 --- a/.changeset/sour-needles-collect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -cleanup set #bugfix diff --git a/.changeset/ten-clouds-collect.md b/.changeset/ten-clouds-collect.md deleted file mode 100644 index 0408383bd03..00000000000 --- a/.changeset/ten-clouds-collect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal diff --git a/CHANGELOG.md b/CHANGELOG.md index bb21a1a904a..336b896ce78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,13 @@ # Changelog Chainlink Core -## 2.11.0 - UNRELEASED + +## 2.11.0 - 2024-04-30 ### Minor Changes +- [#12920](https://github.com/smartcontractkit/chainlink/pull/12920) [`2d2a42876d`](https://github.com/smartcontractkit/chainlink/commit/2d2a42876de5285618c9a9de4b834d078ae8a8cc) Thanks [@ilija42](https://github.com/ilija42)! - Move JuelsPerFeeCoinCacheDuration under JuelsPerFeeCoinCache struct in config. Rename JuelsPerFeeCoinCacheDuration to updateInterval. Add stalenessAlertThreshold to JuelsPerFeeCoinCache config. + StalenessAlertThreshold cfg option has a default of 24 hours which means that it doesn't have to be set unless we want to override the duration after which a stale cache should start throwing errors. + - [#12348](https://github.com/smartcontractkit/chainlink/pull/12348) [`efead72965`](https://github.com/smartcontractkit/chainlink/commit/efead72965fec7e822a16f4d50cc0e5a27dd4640) Thanks [@reductionista](https://github.com/reductionista)! - Update config for zkevm polygon chains - [#12082](https://github.com/smartcontractkit/chainlink/pull/12082) [`608ea0a467`](https://github.com/smartcontractkit/chainlink/commit/608ea0a467ee36e15fdc654a88494ae579d778a6) Thanks [@dhaidashenko](https://github.com/dhaidashenko)! - HeadTracker now respects the `FinalityTagEnabled` config option. If the flag is enabled, HeadTracker backfills blocks up to the latest finalized block provided by the corresponding RPC call. To address potential misconfigurations, `HistoryDepth` is now calculated from the latest finalized block instead of the head. NOTE: Consumers (e.g. TXM and LogPoller) do not fully utilize Finality Tag yet. @@ -26,8 +30,6 @@ - [#12496](https://github.com/smartcontractkit/chainlink/pull/12496) [`31350477ae`](https://github.com/smartcontractkit/chainlink/commit/31350477ae51f00e035b1b8c50775e5955258ac1) Thanks [@silaslenihan](https://github.com/silaslenihan)! - Change LimitTransfer gasLimit type from uint32 to uint64 -- [#12622](https://github.com/smartcontractkit/chainlink/pull/12622) [`a2bdcf51ef`](https://github.com/smartcontractkit/chainlink/commit/a2bdcf51efc1efbbac21745b260bd130dbb1ce3d) Thanks [@HenryNguyen5](https://github.com/HenryNguyen5)! - Add table support to "type" property for step definitions - - [#12339](https://github.com/smartcontractkit/chainlink/pull/12339) [`96d2fe13b8`](https://github.com/smartcontractkit/chainlink/commit/96d2fe13b8510631bbc92ffd20a4d923b93002e6) Thanks [@dhaidashenko](https://github.com/dhaidashenko)! - Add the `pool_rpc_node_highest_finalized_block` metric that tracks the highest finalized block seen per RPC. If `FinalityTagEnabled = true`, a positive `NodePool.FinalizedBlockPollInterval` is needed to collect the metric. If the finality tag is not enabled, the metric is populated with a calculated latest finalized block based on the latest head and finality depth. - [#12473](https://github.com/smartcontractkit/chainlink/pull/12473) [`f1d1f249eb`](https://github.com/smartcontractkit/chainlink/commit/f1d1f249ebecb37da7eacbc4cc12e1eb0205f29a) Thanks [@justinkaseman](https://github.com/justinkaseman)! - Copy common transmitter methods into FunctionsContractTransmitter to enable product specific modification @@ -36,9 +38,12 @@ - [#12578](https://github.com/smartcontractkit/chainlink/pull/12578) [`ffd492295f`](https://github.com/smartcontractkit/chainlink/commit/ffd492295f03de8c3b946a003dacbded731d7899) Thanks [@RensR](https://github.com/RensR)! - Remove 0.6 and 0.7 Solidity source code - ### Patch Changes +- [#12973](https://github.com/smartcontractkit/chainlink/pull/12973) [`02d3f2fee9`](https://github.com/smartcontractkit/chainlink/commit/02d3f2fee9269b85e9500ae720d15bec6c5e0d63) Thanks [@george-dorin](https://github.com/george-dorin)! - JuelsPerFeeCoinCache is enabled by default for OCR2 jobs, added `Disable` field under [pluginConfig.JuelsPerFeeCoinCache] tag to disable this feature (e.g. Disable=true) + +- [#12920](https://github.com/smartcontractkit/chainlink/pull/12920) [`be50a8370a`](https://github.com/smartcontractkit/chainlink/commit/be50a8370a0f604fbe9612e38479ccfa5ceb1ebd) Thanks [@ilija42](https://github.com/ilija42)! - Fix in memory data source cache changes/bug that only allowed pipeline results where none of the data sources failed. #bugfix + - [#12570](https://github.com/smartcontractkit/chainlink/pull/12570) [`2d33524a35`](https://github.com/smartcontractkit/chainlink/commit/2d33524a3539e32ac32a84c4600e6cdfb8e01cf3) Thanks [@samsondav](https://github.com/samsondav)! - VerboseLogging is now turned on by default. You may disable if this results in excessive log volume. Disable like so: @@ -56,7 +61,7 @@ automatically increased to the number of mercury jobs if this exceeds the configured value. -- [#12540](https://github.com/smartcontractkit/chainlink/pull/12540) [`17c037678d`](https://github.com/smartcontractkit/chainlink/commit/17c037678d05c88f28a28a3ac760c742f549d5ec) Thanks [@RyanRHall](https://github.com/RyanRHall)! - change auto 2.3 flat fees from link to USD +- [#12540](https://github.com/smartcontractkit/chainlink/pull/12540) [`17c037678d`](https://github.com/smartcontractkit/chainlink/commit/17c037678d05c88f28a28a3ac760c742f549d5ec) Thanks [@RyanRHall](https://github.com/RyanRHall)! - Change auto 2.3 flat fees from link to USD - [#12696](https://github.com/smartcontractkit/chainlink/pull/12696) [`ee52be7cf9`](https://github.com/smartcontractkit/chainlink/commit/ee52be7cf90076677b1e96e3b294f284e798194f) Thanks [@KuphJr](https://github.com/KuphJr)! - Remove LogPoller filters for outdated Functions coordinator contracts @@ -99,7 +104,7 @@ - [#12564](https://github.com/smartcontractkit/chainlink/pull/12564) [`246762ceeb`](https://github.com/smartcontractkit/chainlink/commit/246762ceebba7923641ec00e66ae1aaf59bbcdc2) Thanks [@mateusz-sekara](https://github.com/mateusz-sekara)! - Exposing information about LogPoller finality violation via Healthy method. It's raised whenever LogPoller sees reorg deeper than the finality -- [#12575](https://github.com/smartcontractkit/chainlink/pull/12575) [`23254c4bf5`](https://github.com/smartcontractkit/chainlink/commit/23254c4bf577e84b71bda1d9a8b2c11e7b548267) Thanks [@augustbleeds](https://github.com/augustbleeds)! - update starknet relayer to fix nonce issue. introduces optional api-key for starknet toml config. +- [#12575](https://github.com/smartcontractkit/chainlink/pull/12575) [`23254c4bf5`](https://github.com/smartcontractkit/chainlink/commit/23254c4bf577e84b71bda1d9a8b2c11e7b548267) Thanks [@augustbleeds](https://github.com/augustbleeds)! - Update starknet relayer to fix nonce issue. introduces optional api-key for starknet toml config. - [#12353](https://github.com/smartcontractkit/chainlink/pull/12353) [`07c9f6cadd`](https://github.com/smartcontractkit/chainlink/commit/07c9f6cadd449989b21977af461305ded8e5b2f0) Thanks [@amit-momin](https://github.com/amit-momin)! - Fixed a race condition bug around EVM nonce management, which could cause the Node to skip a nonce and get stuck. @@ -107,11 +112,11 @@ - [#12484](https://github.com/smartcontractkit/chainlink/pull/12484) [`590cad6126`](https://github.com/smartcontractkit/chainlink/commit/590cad61269c75a6b22be1f6a73c74adfd1baa40) Thanks [@mateusz-sekara](https://github.com/mateusz-sekara)! - Making LogPoller's replay more robust by backfilling up to finalized block and processing rest in the main loop -- [#12612](https://github.com/smartcontractkit/chainlink/pull/12612) [`d44abe3769`](https://github.com/smartcontractkit/chainlink/commit/d44abe37693d6995377fa1329e433e7fba26885d) Thanks [@RensR](https://github.com/RensR)! - upgraded transmission to 0.8.19 +- [#12612](https://github.com/smartcontractkit/chainlink/pull/12612) [`d44abe3769`](https://github.com/smartcontractkit/chainlink/commit/d44abe37693d6995377fa1329e433e7fba26885d) Thanks [@RensR](https://github.com/RensR)! - Upgraded transmission to 0.8.19 - [#12444](https://github.com/smartcontractkit/chainlink/pull/12444) [`dde7fdff33`](https://github.com/smartcontractkit/chainlink/commit/dde7fdff33cfc0690844cf0a88295bef57e2a269) Thanks [@ogtownsend](https://github.com/ogtownsend)! - Updating prometheus metrics for Automation log triggers -- [#12479](https://github.com/smartcontractkit/chainlink/pull/12479) [`93762ccbd8`](https://github.com/smartcontractkit/chainlink/commit/93762ccbd868b9e227abf3220afb9ad22ba41b92) Thanks [@jinhoonbang](https://github.com/jinhoonbang)! - update solc version for vrf v2.5 coordinators +- [#12479](https://github.com/smartcontractkit/chainlink/pull/12479) [`93762ccbd8`](https://github.com/smartcontractkit/chainlink/commit/93762ccbd868b9e227abf3220afb9ad22ba41b92) Thanks [@jinhoonbang](https://github.com/jinhoonbang)! - Update solc version for vrf v2.5 coordinators - [#12337](https://github.com/smartcontractkit/chainlink/pull/12337) [`195b504a93`](https://github.com/smartcontractkit/chainlink/commit/195b504a93b1a241c1981ec21726e4b722d40b2b) Thanks [@samsondav](https://github.com/samsondav)! - Mercury jobs can now broadcast to multiple mercury servers. @@ -132,16 +137,13 @@ - [#11899](https://github.com/smartcontractkit/chainlink/pull/11899) [`67560b9f1d`](https://github.com/smartcontractkit/chainlink/commit/67560b9f1dc052712a76eeb245fba12f2daf8e8d) Thanks [@DylanTinianov](https://github.com/DylanTinianov)! - Refactor EVM ORMs to remove pg dependency -- [#12531](https://github.com/smartcontractkit/chainlink/pull/12531) [`88e010d604`](https://github.com/smartcontractkit/chainlink/commit/88e010d604682c54c4f99e0a0916f94c0d13ece6) Thanks [@jinhoonbang](https://github.com/jinhoonbang)! - increase num optimizations to 500 for vrf v2.5 coordinator - -- [#12375](https://github.com/smartcontractkit/chainlink/pull/12375) [`831aea819d`](https://github.com/smartcontractkit/chainlink/commit/831aea819dd6b3415770cc927c4857a1da4557b5) Thanks [@shileiwill](https://github.com/shileiwill)! - add liquidity pool for automation 2.3 - -- [#12412](https://github.com/smartcontractkit/chainlink/pull/12412) [`83c8688a14`](https://github.com/smartcontractkit/chainlink/commit/83c8688a14ac04111f999d132673ebaf6a364b4a) Thanks [@poopoothegorilla](https://github.com/poopoothegorilla)! - bump grafana to 1.1.1 - -- [#12248](https://github.com/smartcontractkit/chainlink/pull/12248) [`e1950769ee`](https://github.com/smartcontractkit/chainlink/commit/e1950769ee3ff2a40ca5772b9634c45f8be241cc) Thanks [@FelixFan1992](https://github.com/FelixFan1992)! - add version support for automation registry 2.\* +- [#12531](https://github.com/smartcontractkit/chainlink/pull/12531) [`88e010d604`](https://github.com/smartcontractkit/chainlink/commit/88e010d604682c54c4f99e0a0916f94c0d13ece6) Thanks [@jinhoonbang](https://github.com/jinhoonbang)! - Increase num optimizations to 500 for vrf v2.5 coordinator +- [#12375](https://github.com/smartcontractkit/chainlink/pull/12375) [`831aea819d`](https://github.com/smartcontractkit/chainlink/commit/831aea819dd6b3415770cc927c4857a1da4557b5) Thanks [@shileiwill](https://github.com/shileiwill)! - Add liquidity pool for automation 2.3 +- [#12412](https://github.com/smartcontractkit/chainlink/pull/12412) [`83c8688a14`](https://github.com/smartcontractkit/chainlink/commit/83c8688a14ac04111f999d132673ebaf6a364b4a) Thanks [@poopoothegorilla](https://github.com/poopoothegorilla)! - Bump grafana to 1.1.1 +- [#12248](https://github.com/smartcontractkit/chainlink/pull/12248) [`e1950769ee`](https://github.com/smartcontractkit/chainlink/commit/e1950769ee3ff2a40ca5772b9634c45f8be241cc) Thanks [@FelixFan1992](https://github.com/FelixFan1992)! - Add version support for automation registry 2.\* ## 2.10.0 - 2024-04-05 From 9ca4f04f97af46d64e7f17b8afedfd0f009f0d63 Mon Sep 17 00:00:00 2001 From: Sneha Agnihotri <180277+snehaagni@users.noreply.github.com> Date: Wed, 1 May 2024 15:51:18 -0700 Subject: [PATCH 25/45] Bump version and update CHANGELOG for core v2.12.0 (#13075) Signed-off-by: Sneha Agnihotri --- .changeset/beige-socks-cover.md | 5 - .changeset/brave-dots-breathe.md | 7 -- .changeset/brown-penguins-grin.md | 5 - .changeset/chilled-bikes-unite.md | 5 - .changeset/curvy-weeks-cover.md | 5 - .changeset/cyan-crabs-explode.md | 5 - .changeset/dull-dingos-remember.md | 5 - .changeset/early-paws-end.md | 5 - .changeset/empty-tomatoes-yawn.md | 5 - .changeset/fast-students-accept.md | 5 - .changeset/flat-guests-marry.md | 6 -- .changeset/forty-feet-train.md | 5 - .changeset/four-shoes-trade.md | 5 - .changeset/fresh-lizards-love.md | 5 - .changeset/fresh-moles-explode.md | 5 - .changeset/fresh-rice-learn.md | 5 - .changeset/fuzzy-pans-destroy.md | 5 - .changeset/gold-bottles-tell.md | 5 - .changeset/great-rockets-obey.md | 5 - .changeset/hot-dryers-flash.md | 5 - .changeset/hungry-ways-add.md | 6 -- .changeset/kind-deers-leave.md | 5 - .changeset/lovely-jeans-confess.md | 6 -- .changeset/lucky-ghosts-give.md | 5 - .changeset/lucky-windows-taste.md | 5 - .changeset/many-pillows-reflect.md | 5 - .changeset/new-forks-grab.md | 5 - .changeset/olive-knives-happen.md | 5 - .changeset/orange-squids-kick.md | 5 - .changeset/perfect-dancers-guess.md | 5 - .changeset/pink-schools-provide.md | 5 - .changeset/plenty-wombats-grab.md | 5 - .changeset/poor-masks-fold.md | 6 -- .changeset/poor-socks-travel.md | 5 - .changeset/pretty-flies-fold.md | 5 - .changeset/pretty-kangaroos-tell.md | 5 - .changeset/proud-toys-travel.md | 5 - .changeset/quick-fishes-heal.md | 5 - .changeset/real-numbers-taste.md | 5 - .changeset/rich-jars-flow.md | 5 - .changeset/silver-otters-play.md | 5 - .changeset/sixty-readers-mix.md | 5 - .changeset/smooth-comics-love.md | 5 - .changeset/soft-hotels-decide.md | 5 - .changeset/sour-jars-cross.md | 13 --- .changeset/spotty-cooks-think.md | 5 - .changeset/stale-terms-march.md | 7 -- .changeset/sweet-sloths-laugh.md | 5 - .changeset/swift-horses-unite.md | 5 - .changeset/tasty-lions-rhyme.md | 5 - .changeset/tender-crews-jam.md | 5 - .changeset/thirty-students-explain.md | 5 - .changeset/tidy-trees-tie.md | 5 - .changeset/tricky-bats-exist.md | 5 - .changeset/two-countries-lay.md | 5 - .changeset/warm-impalas-return.md | 5 - .changeset/weak-emus-reply.md | 5 - .changeset/witty-icons-rhyme.md | 5 - .changeset/witty-numbers-sleep.md | 5 - CHANGELOG.md | 142 ++++++++++++++++++++++++++ package.json | 2 +- 61 files changed, 143 insertions(+), 312 deletions(-) delete mode 100644 .changeset/beige-socks-cover.md delete mode 100644 .changeset/brave-dots-breathe.md delete mode 100644 .changeset/brown-penguins-grin.md delete mode 100644 .changeset/chilled-bikes-unite.md delete mode 100644 .changeset/curvy-weeks-cover.md delete mode 100644 .changeset/cyan-crabs-explode.md delete mode 100644 .changeset/dull-dingos-remember.md delete mode 100644 .changeset/early-paws-end.md delete mode 100644 .changeset/empty-tomatoes-yawn.md delete mode 100644 .changeset/fast-students-accept.md delete mode 100644 .changeset/flat-guests-marry.md delete mode 100644 .changeset/forty-feet-train.md delete mode 100644 .changeset/four-shoes-trade.md delete mode 100644 .changeset/fresh-lizards-love.md delete mode 100644 .changeset/fresh-moles-explode.md delete mode 100644 .changeset/fresh-rice-learn.md delete mode 100644 .changeset/fuzzy-pans-destroy.md delete mode 100644 .changeset/gold-bottles-tell.md delete mode 100644 .changeset/great-rockets-obey.md delete mode 100644 .changeset/hot-dryers-flash.md delete mode 100644 .changeset/hungry-ways-add.md delete mode 100644 .changeset/kind-deers-leave.md delete mode 100644 .changeset/lovely-jeans-confess.md delete mode 100644 .changeset/lucky-ghosts-give.md delete mode 100644 .changeset/lucky-windows-taste.md delete mode 100644 .changeset/many-pillows-reflect.md delete mode 100644 .changeset/new-forks-grab.md delete mode 100644 .changeset/olive-knives-happen.md delete mode 100644 .changeset/orange-squids-kick.md delete mode 100644 .changeset/perfect-dancers-guess.md delete mode 100644 .changeset/pink-schools-provide.md delete mode 100644 .changeset/plenty-wombats-grab.md delete mode 100644 .changeset/poor-masks-fold.md delete mode 100644 .changeset/poor-socks-travel.md delete mode 100644 .changeset/pretty-flies-fold.md delete mode 100644 .changeset/pretty-kangaroos-tell.md delete mode 100644 .changeset/proud-toys-travel.md delete mode 100644 .changeset/quick-fishes-heal.md delete mode 100644 .changeset/real-numbers-taste.md delete mode 100644 .changeset/rich-jars-flow.md delete mode 100644 .changeset/silver-otters-play.md delete mode 100644 .changeset/sixty-readers-mix.md delete mode 100644 .changeset/smooth-comics-love.md delete mode 100644 .changeset/soft-hotels-decide.md delete mode 100644 .changeset/sour-jars-cross.md delete mode 100644 .changeset/spotty-cooks-think.md delete mode 100644 .changeset/stale-terms-march.md delete mode 100644 .changeset/sweet-sloths-laugh.md delete mode 100644 .changeset/swift-horses-unite.md delete mode 100644 .changeset/tasty-lions-rhyme.md delete mode 100644 .changeset/tender-crews-jam.md delete mode 100644 .changeset/thirty-students-explain.md delete mode 100644 .changeset/tidy-trees-tie.md delete mode 100644 .changeset/tricky-bats-exist.md delete mode 100644 .changeset/two-countries-lay.md delete mode 100644 .changeset/warm-impalas-return.md delete mode 100644 .changeset/weak-emus-reply.md delete mode 100644 .changeset/witty-icons-rhyme.md delete mode 100644 .changeset/witty-numbers-sleep.md diff --git a/.changeset/beige-socks-cover.md b/.changeset/beige-socks-cover.md deleted file mode 100644 index 0b7c22d01e5..00000000000 --- a/.changeset/beige-socks-cover.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal changes to core required by change BCF3168 in common to add relayer set diff --git a/.changeset/brave-dots-breathe.md b/.changeset/brave-dots-breathe.md deleted file mode 100644 index f1ae4f4d21e..00000000000 --- a/.changeset/brave-dots-breathe.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"chainlink": minor ---- - -Added a new CLI command, `blocks find-lca,` which finds the latest block that is available in both the database and on the chain for the specified chain. -Added a new CLI command, `node remove-blocks,` which removes all blocks and logs greater than or equal to the specified block number. -#nops #added diff --git a/.changeset/brown-penguins-grin.md b/.changeset/brown-penguins-grin.md deleted file mode 100644 index 24a06a030fc..00000000000 --- a/.changeset/brown-penguins-grin.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Fix in memory data source cache changes/bug that only allowed pipeline results where none of the data sources failed. #bugfix diff --git a/.changeset/chilled-bikes-unite.md b/.changeset/chilled-bikes-unite.md deleted file mode 100644 index e3e54852002..00000000000 --- a/.changeset/chilled-bikes-unite.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal Add script to create test database user and update docs diff --git a/.changeset/curvy-weeks-cover.md b/.changeset/curvy-weeks-cover.md deleted file mode 100644 index 0b19df8ad16..00000000000 --- a/.changeset/curvy-weeks-cover.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#wip Keystone contract wrappers updated diff --git a/.changeset/cyan-crabs-explode.md b/.changeset/cyan-crabs-explode.md deleted file mode 100644 index 5018e2d555c..00000000000 --- a/.changeset/cyan-crabs-explode.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Add support for workflow jobs to Operator UI #wip #added diff --git a/.changeset/dull-dingos-remember.md b/.changeset/dull-dingos-remember.md deleted file mode 100644 index 7c1b748cff7..00000000000 --- a/.changeset/dull-dingos-remember.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -use safe lib for approve #bugfix diff --git a/.changeset/early-paws-end.md b/.changeset/early-paws-end.md deleted file mode 100644 index 1a3edb5083f..00000000000 --- a/.changeset/early-paws-end.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -generate gethwrappers for updating node operators in capability registry #internal diff --git a/.changeset/empty-tomatoes-yawn.md b/.changeset/empty-tomatoes-yawn.md deleted file mode 100644 index 3f6e94b79a9..00000000000 --- a/.changeset/empty-tomatoes-yawn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Add a comment to Chain Reader Service constructor that specifies that anonymous events are not supported. diff --git a/.changeset/fast-students-accept.md b/.changeset/fast-students-accept.md deleted file mode 100644 index 8813f3a7812..00000000000 --- a/.changeset/fast-students-accept.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal Optimize workflow engine tests diff --git a/.changeset/flat-guests-marry.md b/.changeset/flat-guests-marry.md deleted file mode 100644 index c1eb6549a96..00000000000 --- a/.changeset/flat-guests-marry.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"chainlink": minor ---- - -#internal Gas Estimator L1Oracles to be chain specific -#removed cmd/arbgas diff --git a/.changeset/forty-feet-train.md b/.changeset/forty-feet-train.md deleted file mode 100644 index f5ea60fd061..00000000000 --- a/.changeset/forty-feet-train.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Bumping chainlink-automation version to v1.0.3 diff --git a/.changeset/four-shoes-trade.md b/.changeset/four-shoes-trade.md deleted file mode 100644 index cb5c9f4be6b..00000000000 --- a/.changeset/four-shoes-trade.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Removed AppConfig from Evm config #internal diff --git a/.changeset/fresh-lizards-love.md b/.changeset/fresh-lizards-love.md deleted file mode 100644 index 8e6e5d5cfef..00000000000 --- a/.changeset/fresh-lizards-love.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal Updates required to work with chainlink-common changes to support grpc streams for capabilities diff --git a/.changeset/fresh-moles-explode.md b/.changeset/fresh-moles-explode.md deleted file mode 100644 index 205002b40a0..00000000000 --- a/.changeset/fresh-moles-explode.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -core/chains/evm/logpoller: Stricter finality checks in LogPoller, to be more robust during rpc failover events #updated diff --git a/.changeset/fresh-rice-learn.md b/.changeset/fresh-rice-learn.md deleted file mode 100644 index 6425cdd4581..00000000000 --- a/.changeset/fresh-rice-learn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Moved test functions under evm package to support evm extraction #internal diff --git a/.changeset/fuzzy-pans-destroy.md b/.changeset/fuzzy-pans-destroy.md deleted file mode 100644 index 3cff19f8d8a..00000000000 --- a/.changeset/fuzzy-pans-destroy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Use sqlutil instead of pg.Opts/Q/Queryer #internal diff --git a/.changeset/gold-bottles-tell.md b/.changeset/gold-bottles-tell.md deleted file mode 100644 index 5289f368a55..00000000000 --- a/.changeset/gold-bottles-tell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#added : Re-enable abandoned transaction tracker diff --git a/.changeset/great-rockets-obey.md b/.changeset/great-rockets-obey.md deleted file mode 100644 index b90bc810a01..00000000000 --- a/.changeset/great-rockets-obey.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#wip Keystone wrapper regenerate diff --git a/.changeset/hot-dryers-flash.md b/.changeset/hot-dryers-flash.md deleted file mode 100644 index 8423420589d..00000000000 --- a/.changeset/hot-dryers-flash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -core/services: update llo & versioning to use sqlutil #internal diff --git a/.changeset/hungry-ways-add.md b/.changeset/hungry-ways-add.md deleted file mode 100644 index 657494de605..00000000000 --- a/.changeset/hungry-ways-add.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"chainlink": patch ---- - -#bugfix -vrf fix replay number of blocks logic and add logging for job specs diff --git a/.changeset/kind-deers-leave.md b/.changeset/kind-deers-leave.md deleted file mode 100644 index ef88e78241c..00000000000 --- a/.changeset/kind-deers-leave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -bump mockery in makefile #updated diff --git a/.changeset/lovely-jeans-confess.md b/.changeset/lovely-jeans-confess.md deleted file mode 100644 index 50fc70c2c14..00000000000 --- a/.changeset/lovely-jeans-confess.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"chainlink": minor ---- - -#nops : Enable configurable client error regexes for error classification -#added : New toml configuration options for [EVM.NodePool.Errors] to pass regexes on NonceTooLow, NonceTooHigh, ReplacementTransactionUnderpriced, LimitReached, TransactionAlreadyInMempool, TerminallyUnderpriced, InsufficientEth, TxFeeExceedsCap, L2FeeTooLow, L2FeeTooHigh, L2Full, TransactionAlreadyMined, Fatal, and ServiceUnavailable. diff --git a/.changeset/lucky-ghosts-give.md b/.changeset/lucky-ghosts-give.md deleted file mode 100644 index 2ce47a6978b..00000000000 --- a/.changeset/lucky-ghosts-give.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -core/services/keystore: switch to sqlutil.DataStore #internal diff --git a/.changeset/lucky-windows-taste.md b/.changeset/lucky-windows-taste.md deleted file mode 100644 index bfcf559adb5..00000000000 --- a/.changeset/lucky-windows-taste.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Validate support for postgresql-client 16, and update docker image's bundled postgresql-client from 15 to 16. #nops #updated diff --git a/.changeset/many-pillows-reflect.md b/.changeset/many-pillows-reflect.md deleted file mode 100644 index 6de57ecc2a4..00000000000 --- a/.changeset/many-pillows-reflect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -core/services/keeper: switch to sqlutil.DataSource #internal diff --git a/.changeset/new-forks-grab.md b/.changeset/new-forks-grab.md deleted file mode 100644 index 350b5baafb0..00000000000 --- a/.changeset/new-forks-grab.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Drop unused queryTimeout config from TXM strategy #internal diff --git a/.changeset/olive-knives-happen.md b/.changeset/olive-knives-happen.md deleted file mode 100644 index 7f522c96ff1..00000000000 --- a/.changeset/olive-knives-happen.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal Generic Plugin `onchainSigningStrategy` support diff --git a/.changeset/orange-squids-kick.md b/.changeset/orange-squids-kick.md deleted file mode 100644 index a934e70063d..00000000000 --- a/.changeset/orange-squids-kick.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal Remote Trigger setup diff --git a/.changeset/perfect-dancers-guess.md b/.changeset/perfect-dancers-guess.md deleted file mode 100644 index 6ee4099c45a..00000000000 --- a/.changeset/perfect-dancers-guess.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal Rename workflow tags to labels diff --git a/.changeset/pink-schools-provide.md b/.changeset/pink-schools-provide.md deleted file mode 100644 index 6b2aa5ea0c4..00000000000 --- a/.changeset/pink-schools-provide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#bugfix Fixed an issue where the `rebroadcast-transactions` commands did not execute config validation. diff --git a/.changeset/plenty-wombats-grab.md b/.changeset/plenty-wombats-grab.md deleted file mode 100644 index 84fb96f8b80..00000000000 --- a/.changeset/plenty-wombats-grab.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#wip Regenerate Keystone wrappers diff --git a/.changeset/poor-masks-fold.md b/.changeset/poor-masks-fold.md deleted file mode 100644 index 1564aa0791f..00000000000 --- a/.changeset/poor-masks-fold.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"chainlink": minor ---- - -Move JuelsPerFeeCoinCacheDuration under JuelsPerFeeCoinCache struct in config. Rename JuelsPerFeeCoinCacheDuration to updateInterval. Add stalenessAlertThreshold to JuelsPerFeeCoinCache config. -StalenessAlertThreshold cfg option has a default of 24 hours which means that it doesn't have to be set unless we want to override the duration after which a stale cache should start throwing errors. diff --git a/.changeset/poor-socks-travel.md b/.changeset/poor-socks-travel.md deleted file mode 100644 index 88986845095..00000000000 --- a/.changeset/poor-socks-travel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -core/services/ocr2/plugins/ocr2keeper/evmregister/v21/upkeepstate: use sqlutil instead of pg.QOpts #internal diff --git a/.changeset/pretty-flies-fold.md b/.changeset/pretty-flies-fold.md deleted file mode 100644 index d67a3117e14..00000000000 --- a/.changeset/pretty-flies-fold.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -cor/services/relay/evm/mercury: switch to sqlutil.DataStore #internal diff --git a/.changeset/pretty-kangaroos-tell.md b/.changeset/pretty-kangaroos-tell.md deleted file mode 100644 index 946869b1ca0..00000000000 --- a/.changeset/pretty-kangaroos-tell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Add check for valid semvar value for changeset file #internal diff --git a/.changeset/proud-toys-travel.md b/.changeset/proud-toys-travel.md deleted file mode 100644 index e2b1f0c7269..00000000000 --- a/.changeset/proud-toys-travel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Improving LogPoller read queries by properly sorting by multiple columns #updated diff --git a/.changeset/quick-fishes-heal.md b/.changeset/quick-fishes-heal.md deleted file mode 100644 index 966e74c843a..00000000000 --- a/.changeset/quick-fishes-heal.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- -#changed -Added prefix `RPCClient returned error ({RPC_NAME})` to RPC errors to simplify filtering of RPC related issues. diff --git a/.changeset/real-numbers-taste.md b/.changeset/real-numbers-taste.md deleted file mode 100644 index d9f545444c2..00000000000 --- a/.changeset/real-numbers-taste.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -core/services/functions: switch to sqlutil.DataStore #internal diff --git a/.changeset/rich-jars-flow.md b/.changeset/rich-jars-flow.md deleted file mode 100644 index cb72503fe0d..00000000000 --- a/.changeset/rich-jars-flow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Narrowing topic, data_word indexes by adding (evm_chain_id, address, event_sig) to the index definition #db_update diff --git a/.changeset/silver-otters-play.md b/.changeset/silver-otters-play.md deleted file mode 100644 index 433011b5c76..00000000000 --- a/.changeset/silver-otters-play.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Validate user email before asking for a password in the chainlink CLI. diff --git a/.changeset/sixty-readers-mix.md b/.changeset/sixty-readers-mix.md deleted file mode 100644 index a6782a5b276..00000000000 --- a/.changeset/sixty-readers-mix.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Add support for X Layer (X1) #added diff --git a/.changeset/smooth-comics-love.md b/.changeset/smooth-comics-love.md deleted file mode 100644 index 6d41284978d..00000000000 --- a/.changeset/smooth-comics-love.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -update keystone gethwrapper with remove operator function #internal diff --git a/.changeset/soft-hotels-decide.md b/.changeset/soft-hotels-decide.md deleted file mode 100644 index 75b4cadd4e5..00000000000 --- a/.changeset/soft-hotels-decide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -switch more EVM components to use sqlutil.DataStore #internal diff --git a/.changeset/sour-jars-cross.md b/.changeset/sour-jars-cross.md deleted file mode 100644 index b904e8e3dd0..00000000000 --- a/.changeset/sour-jars-cross.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -"chainlink": patch ---- - -#added - -Add configurability to mercury transmitter - -```toml -[Mercury.Transmitter] -TransmitQueueMaxSize = 10_000 # Default -TransmitTimeout = "5s" # Default -``` diff --git a/.changeset/spotty-cooks-think.md b/.changeset/spotty-cooks-think.md deleted file mode 100644 index e645de27beb..00000000000 --- a/.changeset/spotty-cooks-think.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal fix txdb documentation typos diff --git a/.changeset/stale-terms-march.md b/.changeset/stale-terms-march.md deleted file mode 100644 index 72ba417eac3..00000000000 --- a/.changeset/stale-terms-march.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"chainlink": patch ---- - -Bump libocr => fd3cab206b2ca3b7ff207996b95673b2d6303ec4 - -#internal diff --git a/.changeset/sweet-sloths-laugh.md b/.changeset/sweet-sloths-laugh.md deleted file mode 100644 index cbc72913ec9..00000000000 --- a/.changeset/sweet-sloths-laugh.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -core/sessions: switch to sqlutil.DataSource #internal diff --git a/.changeset/swift-horses-unite.md b/.changeset/swift-horses-unite.md deleted file mode 100644 index d9d426efe6d..00000000000 --- a/.changeset/swift-horses-unite.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -core/bridges: use sqlutil.DataSource #internal diff --git a/.changeset/tasty-lions-rhyme.md b/.changeset/tasty-lions-rhyme.md deleted file mode 100644 index b80f1337bce..00000000000 --- a/.changeset/tasty-lions-rhyme.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -add getters #internal diff --git a/.changeset/tender-crews-jam.md b/.changeset/tender-crews-jam.md deleted file mode 100644 index 41b4f0a7633..00000000000 --- a/.changeset/tender-crews-jam.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -vrfv2plus - account for num words in coordinator gas overhead in v2plus wrapper diff --git a/.changeset/thirty-students-explain.md b/.changeset/thirty-students-explain.md deleted file mode 100644 index 0408383bd03..00000000000 --- a/.changeset/thirty-students-explain.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal diff --git a/.changeset/tidy-trees-tie.md b/.changeset/tidy-trees-tie.md deleted file mode 100644 index 7ff415e9de4..00000000000 --- a/.changeset/tidy-trees-tie.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#changed Updating the log trigger log provider's readMaxBatchSize to 56 diff --git a/.changeset/tricky-bats-exist.md b/.changeset/tricky-bats-exist.md deleted file mode 100644 index 3c748353859..00000000000 --- a/.changeset/tricky-bats-exist.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -minor fixes #bugfix diff --git a/.changeset/two-countries-lay.md b/.changeset/two-countries-lay.md deleted file mode 100644 index f3d78e6a2e6..00000000000 --- a/.changeset/two-countries-lay.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -update keystone gethwrapper #internal diff --git a/.changeset/warm-impalas-return.md b/.changeset/warm-impalas-return.md deleted file mode 100644 index 167d831692c..00000000000 --- a/.changeset/warm-impalas-return.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#added JuelsPerFeeCoinCache is enabled by default for OCR2 jobs, added `Disable` field under [pluginConfig.JuelsPerFeeCoinCache] tag to disable this feature (e.g. Disable=true) diff --git a/.changeset/weak-emus-reply.md b/.changeset/weak-emus-reply.md deleted file mode 100644 index ef0c1fe4dae..00000000000 --- a/.changeset/weak-emus-reply.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal Updated FindTxesWithAttemptsAndReceiptsByIdsAndState method signature to accept int64 for tx ID instead of big.Int diff --git a/.changeset/witty-icons-rhyme.md b/.changeset/witty-icons-rhyme.md deleted file mode 100644 index 25d9cf3b1d3..00000000000 --- a/.changeset/witty-icons-rhyme.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -offchain settlement fix #bugfix diff --git a/.changeset/witty-numbers-sleep.md b/.changeset/witty-numbers-sleep.md deleted file mode 100644 index d42664d9f76..00000000000 --- a/.changeset/witty-numbers-sleep.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Support for retention in LogPoller's filters registered by ContractTransmitter #changed diff --git a/CHANGELOG.md b/CHANGELOG.md index 336b896ce78..314626a0bd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,145 @@ # Changelog Chainlink Core +## 2.12.0 - UNRELEASED + +### Minor Changes + +- [#13000](https://github.com/smartcontractkit/chainlink/pull/13000) [`1b994043b0`](https://github.com/smartcontractkit/chainlink/commit/1b994043b00cad9e0c900b6d12173dd1008480a5) Thanks [@ettec](https://github.com/ettec)! - #internal changes to core required by change BCF3168 in common to add relayer set + +- [#12867](https://github.com/smartcontractkit/chainlink/pull/12867) [`27d9413286`](https://github.com/smartcontractkit/chainlink/commit/27d941328655e0cde608c1eff47de736c11e2e58) Thanks [@dhaidashenko](https://github.com/dhaidashenko)! - Added a new CLI command, `blocks find-lca,` which finds the latest block that is available in both the database and on the chain for the specified chain. + Added a new CLI command, `node remove-blocks,` which removes all blocks and logs greater than or equal to the specified block number. + #nops #added + +- [#12914](https://github.com/smartcontractkit/chainlink/pull/12914) [`28df745115`](https://github.com/smartcontractkit/chainlink/commit/28df74511568df989944ee92cfd625a5d22a2840) Thanks [@krehermann](https://github.com/krehermann)! - #internal Add script to create test database user and update docs + +- [#12837](https://github.com/smartcontractkit/chainlink/pull/12837) [`f7982fa718`](https://github.com/smartcontractkit/chainlink/commit/f7982fa718cd9dc6563019acd8dfc5a40475df9e) Thanks [@cedric-cordenier](https://github.com/cedric-cordenier)! - Add support for workflow jobs to Operator UI #wip #added + +- [#12686](https://github.com/smartcontractkit/chainlink/pull/12686) [`2e768c150b`](https://github.com/smartcontractkit/chainlink/commit/2e768c150b44eb3ac8e41e7bafdd46911be57397) Thanks [@nolag](https://github.com/nolag)! - Add a comment to Chain Reader Service constructor that specifies that anonymous events are not supported. + +- [#12650](https://github.com/smartcontractkit/chainlink/pull/12650) [`6991af26d9`](https://github.com/smartcontractkit/chainlink/commit/6991af26d9fa0e048b72a05f4f9c13f2306c0328) Thanks [@silaslenihan](https://github.com/silaslenihan)! - #internal Gas Estimator L1Oracles to be chain specific + #removed cmd/arbgas + +- [#12857](https://github.com/smartcontractkit/chainlink/pull/12857) [`d90229e7a7`](https://github.com/smartcontractkit/chainlink/commit/d90229e7a7011f8dc1c331dffb0ad1eeaddba46f) Thanks [@ettec](https://github.com/ettec)! - #internal Updates required to work with chainlink-common changes to support grpc streams for capabilities + +- [#12605](https://github.com/smartcontractkit/chainlink/pull/12605) [`1d9dd466e2`](https://github.com/smartcontractkit/chainlink/commit/1d9dd466e2933b7558949554b882f29f63d90b9f) Thanks [@reductionista](https://github.com/reductionista)! - core/chains/evm/logpoller: Stricter finality checks in LogPoller, to be more robust during rpc failover events #updated + +- [#12968](https://github.com/smartcontractkit/chainlink/pull/12968) [`c97781582b`](https://github.com/smartcontractkit/chainlink/commit/c97781582bbe0333332b985fb10a06edeaafa524) Thanks [@dimriou](https://github.com/dimriou)! - Moved test functions under evm package to support evm extraction #internal + +- [#12456](https://github.com/smartcontractkit/chainlink/pull/12456) [`78dd3e026a`](https://github.com/smartcontractkit/chainlink/commit/78dd3e026a81cb656b99ac62ce552369573ca736) Thanks [@jmank88](https://github.com/jmank88)! - Use sqlutil instead of pg.Opts/Q/Queryer #internal + +- [#12533](https://github.com/smartcontractkit/chainlink/pull/12533) [`ccb8cd85fe`](https://github.com/smartcontractkit/chainlink/commit/ccb8cd85fef8e3bbe3fb5580277a7bd7f477e6bb) Thanks [@DylanTinianov](https://github.com/DylanTinianov)! - #added : Re-enable abandoned transaction tracker + +- [#12760](https://github.com/smartcontractkit/chainlink/pull/12760) [`3f4573479c`](https://github.com/smartcontractkit/chainlink/commit/3f4573479c32dedf44f04261f9d5d4905f2542c7) Thanks [@DylanTinianov](https://github.com/DylanTinianov)! - #nops : Enable configurable client error regexes for error classification + #added : New toml configuration options for [EVM.NodePool.Errors] to pass regexes on NonceTooLow, NonceTooHigh, ReplacementTransactionUnderpriced, LimitReached, TransactionAlreadyInMempool, TerminallyUnderpriced, InsufficientEth, TxFeeExceedsCap, L2FeeTooLow, L2FeeTooHigh, L2Full, TransactionAlreadyMined, Fatal, and ServiceUnavailable. + +- [#12595](https://github.com/smartcontractkit/chainlink/pull/12595) [`e6d4814bda`](https://github.com/smartcontractkit/chainlink/commit/e6d4814bda908f1c0582b914d5aa803cecf333be) Thanks [@ilija42](https://github.com/ilija42)! - Move JuelsPerFeeCoinCacheDuration under JuelsPerFeeCoinCache struct in config. Rename JuelsPerFeeCoinCacheDuration to updateInterval. Add stalenessAlertThreshold to JuelsPerFeeCoinCache config. + StalenessAlertThreshold cfg option has a default of 24 hours which means that it doesn't have to be set unless we want to override the duration after which a stale cache should start throwing errors. + +- [#12767](https://github.com/smartcontractkit/chainlink/pull/12767) [`8db5ccfb39`](https://github.com/smartcontractkit/chainlink/commit/8db5ccfb39f86c9817fcad28292dbe6500821810) Thanks [@pavel-raykov](https://github.com/pavel-raykov)! - Validate user email before asking for a password in the chainlink CLI. + +- [#12851](https://github.com/smartcontractkit/chainlink/pull/12851) [`40064f0dfe`](https://github.com/smartcontractkit/chainlink/commit/40064f0dfecda6e404993dff056e7a666cca7d26) Thanks [@amit-momin](https://github.com/amit-momin)! - #internal Updated FindTxesWithAttemptsAndReceiptsByIdsAndState method signature to accept int64 for tx ID instead of big.Int + +### Patch Changes + +- [#12907](https://github.com/smartcontractkit/chainlink/pull/12907) [`f0439ec840`](https://github.com/smartcontractkit/chainlink/commit/f0439ec8408b39456a74c37df9a264782ed4725c) Thanks [@ilija42](https://github.com/ilija42)! - Fix in memory data source cache changes/bug that only allowed pipeline results where none of the data sources failed. #bugfix + +- [#12996](https://github.com/smartcontractkit/chainlink/pull/12996) [`0a37c0ed53`](https://github.com/smartcontractkit/chainlink/commit/0a37c0ed5346df509b545c88278c026cb2adf375) Thanks [@DeividasK](https://github.com/DeividasK)! - #wip Keystone contract wrappers updated + +- [#12923](https://github.com/smartcontractkit/chainlink/pull/12923) [`274a988985`](https://github.com/smartcontractkit/chainlink/commit/274a988985e0530676bdfedbdb35dec4cb9fe8b2) Thanks [@shileiwill](https://github.com/shileiwill)! - use safe lib for approve #bugfix + +- [#12991](https://github.com/smartcontractkit/chainlink/pull/12991) [`929312681f`](https://github.com/smartcontractkit/chainlink/commit/929312681fb27529915912e8bd6e4000559ea77f) Thanks [@cds95](https://github.com/cds95)! - generate gethwrappers for updating node operators in capability registry #internal + +- [#12959](https://github.com/smartcontractkit/chainlink/pull/12959) [`e482c79822`](https://github.com/smartcontractkit/chainlink/commit/e482c7982278e232acaaa4b3e9a79165faa35d1c) Thanks [@HenryNguyen5](https://github.com/HenryNguyen5)! - #internal Optimize workflow engine tests + +- [#12754](https://github.com/smartcontractkit/chainlink/pull/12754) [`4d9875ecba`](https://github.com/smartcontractkit/chainlink/commit/4d9875ecba9c7f672a9320d43cdb3d24a529f2ee) Thanks [@amirylm](https://github.com/amirylm)! - Bumping chainlink-automation version to v1.0.3 + +- [#12636](https://github.com/smartcontractkit/chainlink/pull/12636) [`bdc076c139`](https://github.com/smartcontractkit/chainlink/commit/bdc076c1395259298f520d741a3a1b397c3e0037) Thanks [@dimriou](https://github.com/dimriou)! - Removed AppConfig from Evm config #internal + +- [#12880](https://github.com/smartcontractkit/chainlink/pull/12880) [`8337fc821b`](https://github.com/smartcontractkit/chainlink/commit/8337fc821baf8011c6c73203482db85f5a44d7ae) Thanks [@DeividasK](https://github.com/DeividasK)! - #wip Keystone wrapper regenerate + +- [#12807](https://github.com/smartcontractkit/chainlink/pull/12807) [`dd41ee6c1f`](https://github.com/smartcontractkit/chainlink/commit/dd41ee6c1fb79333bfec4e8ef795a859e09e72c8) Thanks [@jmank88](https://github.com/jmank88)! - core/services: update llo & versioning to use sqlutil #internal + +- [#12887](https://github.com/smartcontractkit/chainlink/pull/12887) [`e87b83cd78`](https://github.com/smartcontractkit/chainlink/commit/e87b83cd78595c09061c199916c4bb9145e719b7) Thanks [@jinhoonbang](https://github.com/jinhoonbang)! - #bugfix + vrf fix replay number of blocks logic and add logging for job specs + +- [#12848](https://github.com/smartcontractkit/chainlink/pull/12848) [`91698020fb`](https://github.com/smartcontractkit/chainlink/commit/91698020fb695545eeb4befb2d73e36cc3ded0ab) Thanks [@poopoothegorilla](https://github.com/poopoothegorilla)! - bump mockery in makefile #updated + +- [#12810](https://github.com/smartcontractkit/chainlink/pull/12810) [`1fce16e735`](https://github.com/smartcontractkit/chainlink/commit/1fce16e735e417553c00680a3fcae2e081353095) Thanks [@jmank88](https://github.com/jmank88)! - core/services/keystore: switch to sqlutil.DataStore #internal + +- [#11936](https://github.com/smartcontractkit/chainlink/pull/11936) [`2b38bd8738`](https://github.com/smartcontractkit/chainlink/commit/2b38bd8738b4edf16e9913c90720820bc2b8dbd1) Thanks [@erikburt](https://github.com/erikburt)! - Validate support for postgresql-client 16, and update docker image's bundled postgresql-client from 15 to 16. #nops #updated + +- [#12820](https://github.com/smartcontractkit/chainlink/pull/12820) [`e523aa0bc7`](https://github.com/smartcontractkit/chainlink/commit/e523aa0bc7752fbf11dfbb842c8a411d345f30e7) Thanks [@jmank88](https://github.com/jmank88)! - core/services/keeper: switch to sqlutil.DataSource #internal + +- [#12859](https://github.com/smartcontractkit/chainlink/pull/12859) [`44c9b40e0a`](https://github.com/smartcontractkit/chainlink/commit/44c9b40e0a77be0609c33d06c3101d8a7163c3e7) Thanks [@dimriou](https://github.com/dimriou)! - Drop unused queryTimeout config from TXM strategy #internal + +- [#12909](https://github.com/smartcontractkit/chainlink/pull/12909) [`fa5b22773e`](https://github.com/smartcontractkit/chainlink/commit/fa5b22773e52744d3abab1a05cd12ecc2e103d88) Thanks [@vyzaldysanchez](https://github.com/vyzaldysanchez)! - #internal Generic Plugin `onchainSigningStrategy` support + +- [#12845](https://github.com/smartcontractkit/chainlink/pull/12845) [`63abd08cd5`](https://github.com/smartcontractkit/chainlink/commit/63abd08cd55b6dc31e74c6d3e50597eb8400eeb4) Thanks [@bolekk](https://github.com/bolekk)! - #internal Remote Trigger setup + +- [#12961](https://github.com/smartcontractkit/chainlink/pull/12961) [`e50d38b0bd`](https://github.com/smartcontractkit/chainlink/commit/e50d38b0bddc34aa0b97ae6bdf23c355b5619682) Thanks [@HenryNguyen5](https://github.com/HenryNguyen5)! - #internal Rename workflow tags to labels + +- [#12997](https://github.com/smartcontractkit/chainlink/pull/12997) [`8c8994e242`](https://github.com/smartcontractkit/chainlink/commit/8c8994e24284236645509b4c49152e6270ce0e35) Thanks [@george-dorin](https://github.com/george-dorin)! - #bugfix Fixed an issue where the `rebroadcast-transactions` commands did not execute config validation. + +- [#12888](https://github.com/smartcontractkit/chainlink/pull/12888) [`7c059b2c26`](https://github.com/smartcontractkit/chainlink/commit/7c059b2c26ed6d99a40403b4f690c0f3e08154b4) Thanks [@DeividasK](https://github.com/DeividasK)! - #wip Regenerate Keystone wrappers + +- [#12806](https://github.com/smartcontractkit/chainlink/pull/12806) [`9964dc82e5`](https://github.com/smartcontractkit/chainlink/commit/9964dc82e591f8653adb06f0b149a16e0b6cea40) Thanks [@jmank88](https://github.com/jmank88)! - core/services/ocr2/plugins/ocr2keeper/evmregister/v21/upkeepstate: use sqlutil instead of pg.QOpts #internal + +- [#12818](https://github.com/smartcontractkit/chainlink/pull/12818) [`6a0b4a9b09`](https://github.com/smartcontractkit/chainlink/commit/6a0b4a9b099663e3aed202f48f363afc4d111293) Thanks [@jmank88](https://github.com/jmank88)! - cor/services/relay/evm/mercury: switch to sqlutil.DataStore #internal + +- [#12947](https://github.com/smartcontractkit/chainlink/pull/12947) [`758ffd6da0`](https://github.com/smartcontractkit/chainlink/commit/758ffd6da097adac1f49ceded5e0998cdcb98a29) Thanks [@momentmaker](https://github.com/momentmaker)! - Add check for valid semvar value for changeset file #internal + +- [#13026](https://github.com/smartcontractkit/chainlink/pull/13026) [`e21be2a890`](https://github.com/smartcontractkit/chainlink/commit/e21be2a890a50bd3cbac60c450e3c2d68ddefbd3) Thanks [@mateusz-sekara](https://github.com/mateusz-sekara)! - Improving LogPoller read queries by properly sorting by multiple columns #updated + +- [#12638](https://github.com/smartcontractkit/chainlink/pull/12638) [`bcf7653486`](https://github.com/smartcontractkit/chainlink/commit/bcf76534862b32503f4192e38b7e1cb4dd7e312d) Thanks [@dhaidashenko](https://github.com/dhaidashenko)! - #changed + Added prefix `RPCClient returned error ({RPC_NAME})` to RPC errors to simplify filtering of RPC related issues. + +- [#12811](https://github.com/smartcontractkit/chainlink/pull/12811) [`6b0a7afe23`](https://github.com/smartcontractkit/chainlink/commit/6b0a7afe235399790c066dd725c437403a47a73e) Thanks [@jmank88](https://github.com/jmank88)! - core/services/functions: switch to sqlutil.DataStore #internal + +- [#12786](https://github.com/smartcontractkit/chainlink/pull/12786) [`fbb705c4f1`](https://github.com/smartcontractkit/chainlink/commit/fbb705c4f1338c6e0919d728adee827ec1e2007a) Thanks [@mateusz-sekara](https://github.com/mateusz-sekara)! - Narrowing topic, data_word indexes by adding (evm_chain_id, address, event_sig) to the index definition #db_update + +- [#12747](https://github.com/smartcontractkit/chainlink/pull/12747) [`2729ef76f3`](https://github.com/smartcontractkit/chainlink/commit/2729ef76f34877a2e6e8644b2e67f3e5dfb0c2b6) Thanks [@friedemannf](https://github.com/friedemannf)! - Add support for X Layer (X1) #added + +- [#12979](https://github.com/smartcontractkit/chainlink/pull/12979) [`0c4c24ad8c`](https://github.com/smartcontractkit/chainlink/commit/0c4c24ad8c95e505cd2a29be711cc40e612658b0) Thanks [@cds95](https://github.com/cds95)! - update keystone gethwrapper with remove operator function #internal + +- [#12856](https://github.com/smartcontractkit/chainlink/pull/12856) [`0ec92765cc`](https://github.com/smartcontractkit/chainlink/commit/0ec92765ccd419973f4eab5b0cc38df212f4ad21) Thanks [@jmank88](https://github.com/jmank88)! - switch more EVM components to use sqlutil.DataStore #internal + +- [#12680](https://github.com/smartcontractkit/chainlink/pull/12680) [`f55d8be495`](https://github.com/smartcontractkit/chainlink/commit/f55d8be495a83c97ac5439672563400e12ec2ee7) Thanks [@samsondav](https://github.com/samsondav)! - #added + + Add configurability to mercury transmitter + + ```toml + [Mercury.Transmitter] + TransmitQueueMaxSize = 10_000 # Default + TransmitTimeout = "5s" # Default + ``` + +- [#13059](https://github.com/smartcontractkit/chainlink/pull/13059) [`ea08b5f08d`](https://github.com/smartcontractkit/chainlink/commit/ea08b5f08d84d2ff1ddfa2027660ff58a60219c3) Thanks [@HenryNguyen5](https://github.com/HenryNguyen5)! - #internal fix txdb documentation typos + +- [#12902](https://github.com/smartcontractkit/chainlink/pull/12902) [`d1845e22d3`](https://github.com/smartcontractkit/chainlink/commit/d1845e22d3b057d9d736bc05c30f0db34c84a7e4) Thanks [@samsondav](https://github.com/samsondav)! - Bump libocr => fd3cab206b2ca3b7ff207996b95673b2d6303ec4 + + #internal + +- [#12809](https://github.com/smartcontractkit/chainlink/pull/12809) [`0af4acafbd`](https://github.com/smartcontractkit/chainlink/commit/0af4acafbdf243feea8507e421016933b0e538ca) Thanks [@jmank88](https://github.com/jmank88)! - core/sessions: switch to sqlutil.DataSource #internal + +- [#12808](https://github.com/smartcontractkit/chainlink/pull/12808) [`601c79f891`](https://github.com/smartcontractkit/chainlink/commit/601c79f89120dc0d98db63a528c79644ebb38132) Thanks [@jmank88](https://github.com/jmank88)! - core/bridges: use sqlutil.DataSource #internal + +- [#12903](https://github.com/smartcontractkit/chainlink/pull/12903) [`a293dfe797`](https://github.com/smartcontractkit/chainlink/commit/a293dfe7975b035a71eff7a6197e3ce5a25f1887) Thanks [@shileiwill](https://github.com/shileiwill)! - add getters #internal + +- [#12669](https://github.com/smartcontractkit/chainlink/pull/12669) [`3134ce8868`](https://github.com/smartcontractkit/chainlink/commit/3134ce8868ccc22bd4ae670c8b0bfda5fa78a332) Thanks [@leeyikjiun](https://github.com/leeyikjiun)! - vrfv2plus - account for num words in coordinator gas overhead in v2plus wrapper + +- [#13022](https://github.com/smartcontractkit/chainlink/pull/13022) [`2805fa6c9b`](https://github.com/smartcontractkit/chainlink/commit/2805fa6c9b469d535edcd3d66c08e1d22bbaa2d0) Thanks [@cds95](https://github.com/cds95)! - #internal + +- [#12951](https://github.com/smartcontractkit/chainlink/pull/12951) [`c98ea6413d`](https://github.com/smartcontractkit/chainlink/commit/c98ea6413dcdc02a7d0c82b9b36d3fce97dac94b) Thanks [@ogtownsend](https://github.com/ogtownsend)! - #changed Updating the log trigger log provider's readMaxBatchSize to 56 + +- [#12944](https://github.com/smartcontractkit/chainlink/pull/12944) [`167782c680`](https://github.com/smartcontractkit/chainlink/commit/167782c680b92b1e99ae3e9d1a8b87fd595dd644) Thanks [@shileiwill](https://github.com/shileiwill)! - minor fixes #bugfix + +- [#12906](https://github.com/smartcontractkit/chainlink/pull/12906) [`365c38be8b`](https://github.com/smartcontractkit/chainlink/commit/365c38be8b589d5ffa0b21755dcb40e2e4205652) Thanks [@cds95](https://github.com/cds95)! - update keystone gethwrapper #internal + +- [#12966](https://github.com/smartcontractkit/chainlink/pull/12966) [`ac7d3409ed`](https://github.com/smartcontractkit/chainlink/commit/ac7d3409ed9bc98af970ca75c3b92e41e4fb01cf) Thanks [@george-dorin](https://github.com/george-dorin)! - #added JuelsPerFeeCoinCache is enabled by default for OCR2 jobs, added `Disable` field under [pluginConfig.JuelsPerFeeCoinCache] tag to disable this feature (e.g. Disable=true) + +- [#12916](https://github.com/smartcontractkit/chainlink/pull/12916) [`7ec1d5b7ab`](https://github.com/smartcontractkit/chainlink/commit/7ec1d5b7abb51e100f7a6a48662e33703a589ecb) Thanks [@shileiwill](https://github.com/shileiwill)! - offchain settlement fix #bugfix + +- [#12998](https://github.com/smartcontractkit/chainlink/pull/12998) [`d50936ce38`](https://github.com/smartcontractkit/chainlink/commit/d50936ce3824d7ad6026f630172e9764a34cc08b) Thanks [@mateusz-sekara](https://github.com/mateusz-sekara)! - Support for retention in LogPoller's filters registered by ContractTransmitter #changed ## 2.11.0 - 2024-04-30 @@ -215,6 +355,7 @@ `mercury_transmit_queue_push_error_count` Nops should consider alerting on these. - Mercury now implements a local cache for fetching prices for fees, which ought to reduce latency and load on the mercury server, as well as increasing performance. It is enabled by default and can be configured with the following new config variables: + ``` [Mercury] @@ -239,6 +380,7 @@ # mercury server before retrying. Setting this to zero will wait indefinitely. LatestReportDeadline = "5s" # Default ``` + - New prom metrics for the mercury cache: `mercury_cache_fetch_failure_count` `mercury_cache_hit_count` diff --git a/package.json b/package.json index 759f8aaea4d..c903ac23165 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chainlink", - "version": "2.11.0", + "version": "2.12.0", "description": "node of the decentralized oracle network, bridging on and off-chain computation", "main": "index.js", "scripts": { From 9bd03c99930b504029bbb3eed4ecd1d00509cd49 Mon Sep 17 00:00:00 2001 From: HenryNguyen5 <6404866+HenryNguyen5@users.noreply.github.com> Date: Wed, 1 May 2024 23:20:12 -0400 Subject: [PATCH 26/45] Run short tests once on CI (#13077) --- .github/workflows/ci-core.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml index fbef1b8282c..1d7b58820b0 100644 --- a/.github/workflows/ci-core.yml +++ b/.github/workflows/ci-core.yml @@ -112,7 +112,7 @@ jobs: if: ${{ needs.filter.outputs.changes == 'true' }} uses: ./.github/actions/setup-go - name: Run short tests - if: ${{ needs.filter.outputs.changes == 'true' }} + if: ${{ needs.filter.outputs.changes == 'true' && matrix.type.cmd == 'go_core_tests' }} run: go test -short ./... - name: Setup Solana if: ${{ needs.filter.outputs.changes == 'true' }} From 841fe61daa90b980f1e1622d2f7bd8f850b55462 Mon Sep 17 00:00:00 2001 From: HenryNguyen5 <6404866+HenryNguyen5@users.noreply.github.com> Date: Thu, 2 May 2024 00:38:00 -0400 Subject: [PATCH 27/45] Rename type -> id (#13008) --- .changeset/bright-queens-joke.md | 5 + contracts/.changeset/old-seas-doubt.md | 5 + .../src/v0.8/keystone/CapabilityRegistry.sol | 116 +++++++++------- .../src/v0.8/keystone/test/BaseTest.t.sol | 18 +-- ...CapabilityRegistry_AddCapabilityTest.t.sol | 17 ++- .../CapabilityRegistry_AddNodesTest.t.sol | 46 +++---- ...pabilityRegistry_DeprecateCapability.t.sol | 40 +++--- .../CapabilityRegistry_GetCapabilities.t.sol | 12 +- .../CapabilityRegistry_GetCapabilityIds.t.sol | 4 +- .../keystone_capability_registry.go | 126 +++++++++--------- ...rapper-dependency-versions-do-not-edit.txt | 2 +- core/services/workflows/engine.go | 10 +- core/services/workflows/engine_test.go | 22 +-- core/services/workflows/models.go | 5 +- core/services/workflows/models_test.go | 58 ++++---- core/services/workflows/models_yaml.go | 72 +++++----- core/services/workflows/models_yaml_test.go | 2 +- .../workflows/marshalling/workflow_1.yaml | 6 +- .../workflows/marshalling/workflow_2.yaml | 6 +- .../marshalling/workflow_2_spec.json | 8 +- .../workflows/references/failing_1.yaml | 6 +- .../workflows/references/passing_1.yaml | 6 +- .../workflows/versioning/failing_1.yaml | 6 +- .../workflows/versioning/failing_2.yaml | 6 +- .../workflows/versioning/passing_1.yaml | 6 +- .../fixtures/workflows/workflow_schema.json | 16 +-- core/web/jobs_controller_test.go | 8 +- 27 files changed, 333 insertions(+), 301 deletions(-) create mode 100644 .changeset/bright-queens-joke.md create mode 100644 contracts/.changeset/old-seas-doubt.md diff --git a/.changeset/bright-queens-joke.md b/.changeset/bright-queens-joke.md new file mode 100644 index 00000000000..a9dc2c8eb6d --- /dev/null +++ b/.changeset/bright-queens-joke.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal Keystone - rename type -> id diff --git a/contracts/.changeset/old-seas-doubt.md b/contracts/.changeset/old-seas-doubt.md new file mode 100644 index 00000000000..d559b3f5641 --- /dev/null +++ b/contracts/.changeset/old-seas-doubt.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +#internal Keystone - rename type to id diff --git a/contracts/src/v0.8/keystone/CapabilityRegistry.sol b/contracts/src/v0.8/keystone/CapabilityRegistry.sol index ed3a300ac40..9e0a67434fc 100644 --- a/contracts/src/v0.8/keystone/CapabilityRegistry.sol +++ b/contracts/src/v0.8/keystone/CapabilityRegistry.sol @@ -28,10 +28,10 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { bytes32 p2pId; /// @notice The signer address for application-layer message verification. address signer; - /// @notice The list of capability IDs this node supports. This list is + /// @notice The list of hashed capability IDs this node supports. This list is /// never empty and all capabilities are guaranteed to exist in the /// CapabilityRegistry. - bytes32[] supportedCapabilityIds; + bytes32[] supportedHashedCapabilityIds; } // CapabilityResponseType indicates whether remote response requires @@ -45,10 +45,16 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { } struct Capability { - // Capability type, e.g. "data-streams-reports" + // The `labelledName` is a partially qualified ID for the capability. + // + // Given the following capability ID: {name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}@{version} + // Then we denote the `labelledName` as the `{name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}` portion of the ID. + // + // Ex. id = "data-streams-reports:chain:ethereum@1.0.0" + // labelledName = "data-streams-reports:chain:ethereum" + // // bytes32(string); validation regex: ^[a-z0-9_\-:]{1,32}$ - // Not "type" because that's a reserved keyword in Solidity. - bytes32 capabilityType; + bytes32 labelledName; // Semver, e.g., "1.2.3" // bytes32(string); must be valid Semver + max 32 characters. bytes32 version; @@ -92,8 +98,8 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @notice This error is thrown when trying to add a node without /// capabilities or with capabilities that do not exist. - /// @param capabilityIds The IDs of the capabilities that are being added. - error InvalidNodeCapabilities(bytes32[] capabilityIds); + /// @param hashedCapabilityIds The IDs of the capabilities that are being added. + error InvalidNodeCapabilities(bytes32[] hashedCapabilityIds); /// @notice This event is emitted when a new node is added /// @param p2pId The P2P ID of the node @@ -104,15 +110,15 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// exists. error CapabilityAlreadyExists(); - /// @notice This error is thrown when a capability with the provided ID is + /// @notice This error is thrown when a capability with the provided hashed ID is /// not found. - /// @param capabilityId The ID used for the lookup. - error CapabilityDoesNotExist(bytes32 capabilityId); + /// @param hashedCapabilityId The hashed ID used for the lookup. + error CapabilityDoesNotExist(bytes32 hashedCapabilityId); /// @notice This error is thrown when trying to deprecate a capability that /// is already deprecated. - /// @param capabilityId The ID of the capability that is already deprecated. - error CapabilityAlreadyDeprecated(bytes32 capabilityId); + /// @param hashedCapabilityId The hashed ID of the capability that is already deprecated. + error CapabilityAlreadyDeprecated(bytes32 hashedCapabilityId); /// @notice This error is thrown when trying to add a capability with a /// configuration contract that does not implement the required interface. @@ -138,16 +144,22 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { event NodeOperatorUpdated(uint256 nodeOperatorId, address indexed admin, string name); /// @notice This event is emitted when a new capability is added - /// @param capabilityId The ID of the newly added capability - event CapabilityAdded(bytes32 indexed capabilityId); + /// @param hashedCapabilityId The hashed ID of the newly added capability + event CapabilityAdded(bytes32 indexed hashedCapabilityId); /// @notice This event is emitted when a capability is deprecated - /// @param capabilityId The ID of the deprecated capability - event CapabilityDeprecated(bytes32 indexed capabilityId); + /// @param hashedCapabilityId The hashed ID of the deprecated capability + event CapabilityDeprecated(bytes32 indexed hashedCapabilityId); mapping(bytes32 => Capability) private s_capabilities; - EnumerableSet.Bytes32Set private s_capabilityIds; - EnumerableSet.Bytes32Set private s_deprecatedCapabilityIds; + /// @notice Set of hashed capability IDs. + /// A hashed ID is created by the function `getHashedCapabilityId`. + EnumerableSet.Bytes32Set private s_hashedCapabilityIds; + /// @notice Set of deprecated hashed capability IDs, + /// A hashed ID is created by the function `getHashedCapabilityId`. + /// + /// Deprecated capabilities are skipped by the `getCapabilities` function. + EnumerableSet.Bytes32Set private s_deprecatedHashedCapabilityIds; /// @notice Mapping of node operators mapping(uint256 nodeOperatorId => NodeOperator nodeOperator) private s_nodeOperators; @@ -227,14 +239,15 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { NodeOperator memory nodeOperator = s_nodeOperators[node.nodeOperatorId]; if (msg.sender != nodeOperator.admin) revert AccessForbidden(); - bool nodeExists = s_nodes[node.p2pId].supportedCapabilityIds.length > 0; + bool nodeExists = s_nodes[node.p2pId].supportedHashedCapabilityIds.length > 0; if (nodeExists || bytes32(node.p2pId) == bytes32("")) revert InvalidNodeP2PId(node.p2pId); - if (node.supportedCapabilityIds.length == 0) revert InvalidNodeCapabilities(node.supportedCapabilityIds); + if (node.supportedHashedCapabilityIds.length == 0) + revert InvalidNodeCapabilities(node.supportedHashedCapabilityIds); - for (uint256 j; j < node.supportedCapabilityIds.length; ++j) { - if (!s_capabilityIds.contains(node.supportedCapabilityIds[j])) - revert InvalidNodeCapabilities(node.supportedCapabilityIds); + for (uint256 j; j < node.supportedHashedCapabilityIds.length; ++j) { + if (!s_hashedCapabilityIds.contains(node.supportedHashedCapabilityIds[j])) + revert InvalidNodeCapabilities(node.supportedHashedCapabilityIds); } s_nodes[node.p2pId] = node; @@ -250,9 +263,8 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { } function addCapability(Capability calldata capability) external onlyOwner { - bytes32 capabilityId = getCapabilityID(capability.capabilityType, capability.version); - - if (s_capabilityIds.contains(capabilityId)) revert CapabilityAlreadyExists(); + bytes32 hashedId = getHashedCapabilityId(capability.labelledName, capability.version); + if (s_hashedCapabilityIds.contains(hashedId)) revert CapabilityAlreadyExists(); if (capability.configurationContract != address(0)) { if ( @@ -263,24 +275,26 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { ) revert InvalidCapabilityConfigurationContractInterface(capability.configurationContract); } - s_capabilityIds.add(capabilityId); - s_capabilities[capabilityId] = capability; + s_hashedCapabilityIds.add(hashedId); + s_capabilities[hashedId] = capability; - emit CapabilityAdded(capabilityId); + emit CapabilityAdded(hashedId); } /// @notice Deprecates a capability by adding it to the deprecated list - /// @param capabilityId The ID of the capability to deprecate - function deprecateCapability(bytes32 capabilityId) external onlyOwner { - if (!s_capabilityIds.contains(capabilityId)) revert CapabilityDoesNotExist(capabilityId); - if (s_deprecatedCapabilityIds.contains(capabilityId)) revert CapabilityAlreadyDeprecated(capabilityId); - - s_deprecatedCapabilityIds.add(capabilityId); - emit CapabilityDeprecated(capabilityId); + /// @param hashedCapabilityId The ID of the capability to deprecate + function deprecateCapability(bytes32 hashedCapabilityId) external onlyOwner { + if (!s_hashedCapabilityIds.contains(hashedCapabilityId)) revert CapabilityDoesNotExist(hashedCapabilityId); + if (s_deprecatedHashedCapabilityIds.contains(hashedCapabilityId)) + revert CapabilityAlreadyDeprecated(hashedCapabilityId); + + s_deprecatedHashedCapabilityIds.add(hashedCapabilityId); + emit CapabilityDeprecated(hashedCapabilityId); } - function getCapability(bytes32 capabilityID) public view returns (Capability memory) { - return s_capabilities[capabilityID]; + /// @notice This function returns a Capability by its hashed ID. Use `getHashedCapabilityId` to get the hashed ID. + function getCapability(bytes32 hashedId) public view returns (Capability memory) { + return s_capabilities[hashedId]; } /// @notice Returns all capabilities. This operation will copy capabilities @@ -288,21 +302,23 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// used by view accessors that are queried without any gas fees. /// @return Capability[] An array of capabilities function getCapabilities() external view returns (Capability[] memory) { - bytes32[] memory capabilityIds = s_capabilityIds.values(); + bytes32[] memory hashedCapabilityIds = s_hashedCapabilityIds.values(); // Solidity does not support dynamic arrays in memory, so we create a // fixed-size array and copy the capabilities into it. - Capability[] memory capabilities = new Capability[](capabilityIds.length - s_deprecatedCapabilityIds.length()); + Capability[] memory capabilities = new Capability[]( + hashedCapabilityIds.length - s_deprecatedHashedCapabilityIds.length() + ); // We need to keep track of the new index because we are skipping // deprecated capabilities. uint256 newIndex; - for (uint256 i; i < capabilityIds.length; ++i) { - bytes32 capabilityId = capabilityIds[i]; + for (uint256 i; i < hashedCapabilityIds.length; ++i) { + bytes32 hashedCapabilityId = hashedCapabilityIds[i]; - if (!s_deprecatedCapabilityIds.contains(capabilityId)) { - capabilities[newIndex] = getCapability(capabilityId); + if (!s_deprecatedHashedCapabilityIds.contains(hashedCapabilityId)) { + capabilities[newIndex] = getCapability(hashedCapabilityId); newIndex++; } } @@ -310,16 +326,16 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { return capabilities; } - /// @notice This functions returns a Capability ID packed into a bytes32 for cheaper access + /// @notice This functions returns a capability id that has been hashed to fit into a bytes32 for cheaper access /// @return bytes32 A unique identifier for the capability - function getCapabilityID(bytes32 capabilityType, bytes32 version) public pure returns (bytes32) { - return keccak256(abi.encodePacked(capabilityType, version)); + function getHashedCapabilityId(bytes32 labelledName, bytes32 version) public pure returns (bytes32) { + return keccak256(abi.encodePacked(labelledName, version)); } /// @notice Returns whether a capability is deprecated - /// @param capabilityId The ID of the capability to check + /// @param hashedCapabilityId The hashed ID of the capability to check /// @return bool True if the capability is deprecated, false otherwise - function isCapabilityDeprecated(bytes32 capabilityId) external view returns (bool) { - return s_deprecatedCapabilityIds.contains(capabilityId); + function isCapabilityDeprecated(bytes32 hashedCapabilityId) external view returns (bool) { + return s_deprecatedHashedCapabilityIds.contains(hashedCapabilityId); } } diff --git a/contracts/src/v0.8/keystone/test/BaseTest.t.sol b/contracts/src/v0.8/keystone/test/BaseTest.t.sol index 95c8d1e5d3d..b4d12f7ba73 100644 --- a/contracts/src/v0.8/keystone/test/BaseTest.t.sol +++ b/contracts/src/v0.8/keystone/test/BaseTest.t.sol @@ -11,9 +11,9 @@ contract BaseTest is Test, Constants { CapabilityConfigurationContract internal s_capabilityConfigurationContract; CapabilityRegistry.Capability internal s_basicCapability; CapabilityRegistry.Capability internal s_capabilityWithConfigurationContract; - bytes32 internal s_basicCapabilityId; + bytes32 internal s_basicHashedCapabilityId; bytes32 internal s_capabilityWithConfigurationContractId; - bytes32 internal s_nonExistentCapabilityId; + bytes32 internal s_nonExistentHashedCapabilityId; function setUp() public virtual { vm.startPrank(ADMIN); @@ -21,27 +21,27 @@ contract BaseTest is Test, Constants { s_capabilityConfigurationContract = new CapabilityConfigurationContract(); s_basicCapability = CapabilityRegistry.Capability({ - capabilityType: "data-streams-reports", + labelledName: "data-streams-reports", version: "1.0.0", responseType: CapabilityRegistry.CapabilityResponseType.REPORT, configurationContract: address(0) }); s_capabilityWithConfigurationContract = CapabilityRegistry.Capability({ - capabilityType: "read-ethereum-mainnet-gas-price", + labelledName: "read-ethereum-mainnet-gas-price", version: "1.0.2", responseType: CapabilityRegistry.CapabilityResponseType.OBSERVATION_IDENTICAL, configurationContract: address(s_capabilityConfigurationContract) }); - s_basicCapabilityId = s_capabilityRegistry.getCapabilityID( - s_basicCapability.capabilityType, + s_basicHashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId( + s_basicCapability.labelledName, s_basicCapability.version ); - s_capabilityWithConfigurationContractId = s_capabilityRegistry.getCapabilityID( - s_capabilityWithConfigurationContract.capabilityType, + s_capabilityWithConfigurationContractId = s_capabilityRegistry.getHashedCapabilityId( + s_capabilityWithConfigurationContract.labelledName, s_capabilityWithConfigurationContract.version ); - s_nonExistentCapabilityId = s_capabilityRegistry.getCapabilityID("non-existent-capability", "1.0.0"); + s_nonExistentHashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId("non-existent-capability", "1.0.0"); } function _getNodeOperators() internal view returns (CapabilityRegistry.NodeOperator[] memory) { diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol index cf1bc6c8d73..dbcc0ae1712 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol @@ -47,10 +47,13 @@ contract CapabilityRegistry_AddCapabilityTest is BaseTest { function test_AddCapability_NoConfigurationContract() public { s_capabilityRegistry.addCapability(s_basicCapability); - bytes32 capabilityId = s_capabilityRegistry.getCapabilityID(bytes32("data-streams-reports"), bytes32("1.0.0")); - CapabilityRegistry.Capability memory storedCapability = s_capabilityRegistry.getCapability(capabilityId); + bytes32 hashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId( + bytes32("data-streams-reports"), + bytes32("1.0.0") + ); + CapabilityRegistry.Capability memory storedCapability = s_capabilityRegistry.getCapability(hashedCapabilityId); - assertEq(storedCapability.capabilityType, s_basicCapability.capabilityType); + assertEq(storedCapability.labelledName, s_basicCapability.labelledName); assertEq(storedCapability.version, s_basicCapability.version); assertEq(uint256(storedCapability.responseType), uint256(s_basicCapability.responseType)); assertEq(storedCapability.configurationContract, s_basicCapability.configurationContract); @@ -59,13 +62,13 @@ contract CapabilityRegistry_AddCapabilityTest is BaseTest { function test_AddCapability_WithConfiguration() public { s_capabilityRegistry.addCapability(s_capabilityWithConfigurationContract); - bytes32 capabilityId = s_capabilityRegistry.getCapabilityID( - bytes32(s_capabilityWithConfigurationContract.capabilityType), + bytes32 hashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId( + bytes32(s_capabilityWithConfigurationContract.labelledName), bytes32(s_capabilityWithConfigurationContract.version) ); - CapabilityRegistry.Capability memory storedCapability = s_capabilityRegistry.getCapability(capabilityId); + CapabilityRegistry.Capability memory storedCapability = s_capabilityRegistry.getCapability(hashedCapabilityId); - assertEq(storedCapability.capabilityType, s_capabilityWithConfigurationContract.capabilityType); + assertEq(storedCapability.labelledName, s_capabilityWithConfigurationContract.labelledName); assertEq(storedCapability.version, s_capabilityWithConfigurationContract.version); assertEq(uint256(storedCapability.responseType), uint256(s_capabilityWithConfigurationContract.responseType)); assertEq(storedCapability.configurationContract, s_capabilityWithConfigurationContract.configurationContract); diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol index fe85c144eea..e179cc5cea6 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol @@ -22,14 +22,14 @@ contract CapabilityRegistry_AddNodesTest is BaseTest { changePrank(STRANGER); CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); - bytes32[] memory capabilityIds = new bytes32[](1); - capabilityIds[0] = s_basicCapabilityId; + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; nodes[0] = CapabilityRegistry.Node({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - supportedCapabilityIds: capabilityIds + supportedHashedCapabilityIds: hashedCapabilityIds }); vm.expectRevert(CapabilityRegistry.AccessForbidden.selector); @@ -40,14 +40,14 @@ contract CapabilityRegistry_AddNodesTest is BaseTest { changePrank(NODE_OPERATOR_ONE_ADMIN); CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); - bytes32[] memory capabilityIds = new bytes32[](1); - capabilityIds[0] = s_basicCapabilityId; + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; nodes[0] = CapabilityRegistry.Node({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - supportedCapabilityIds: capabilityIds + supportedHashedCapabilityIds: hashedCapabilityIds }); s_capabilityRegistry.addNodes(nodes); @@ -59,14 +59,14 @@ contract CapabilityRegistry_AddNodesTest is BaseTest { changePrank(NODE_OPERATOR_ONE_ADMIN); CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); - bytes32[] memory capabilityIds = new bytes32[](1); - capabilityIds[0] = s_basicCapabilityId; + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; nodes[0] = CapabilityRegistry.Node({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: bytes32(""), signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - supportedCapabilityIds: capabilityIds + supportedHashedCapabilityIds: hashedCapabilityIds }); vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeP2PId.selector, bytes32(""))); @@ -77,15 +77,15 @@ contract CapabilityRegistry_AddNodesTest is BaseTest { changePrank(NODE_OPERATOR_ONE_ADMIN); CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); - bytes32[] memory capabilityIds = new bytes32[](0); + bytes32[] memory hashedCapabilityIds = new bytes32[](0); nodes[0] = CapabilityRegistry.Node({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - supportedCapabilityIds: capabilityIds + supportedHashedCapabilityIds: hashedCapabilityIds }); - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeCapabilities.selector, capabilityIds)); + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); s_capabilityRegistry.addNodes(nodes); } @@ -93,17 +93,17 @@ contract CapabilityRegistry_AddNodesTest is BaseTest { changePrank(NODE_OPERATOR_ONE_ADMIN); CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); - bytes32[] memory capabilityIds = new bytes32[](1); - capabilityIds[0] = s_nonExistentCapabilityId; + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_nonExistentHashedCapabilityId; nodes[0] = CapabilityRegistry.Node({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - supportedCapabilityIds: capabilityIds + supportedHashedCapabilityIds: hashedCapabilityIds }); - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeCapabilities.selector, capabilityIds)); + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); s_capabilityRegistry.addNodes(nodes); } @@ -111,15 +111,15 @@ contract CapabilityRegistry_AddNodesTest is BaseTest { changePrank(NODE_OPERATOR_ONE_ADMIN); CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); - bytes32[] memory capabilityIds = new bytes32[](2); - capabilityIds[0] = s_basicCapabilityId; - capabilityIds[1] = s_capabilityWithConfigurationContractId; + bytes32[] memory hashedCapabilityIds = new bytes32[](2); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; nodes[0] = CapabilityRegistry.Node({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - supportedCapabilityIds: capabilityIds + supportedHashedCapabilityIds: hashedCapabilityIds }); vm.expectEmit(address(s_capabilityRegistry)); @@ -129,8 +129,8 @@ contract CapabilityRegistry_AddNodesTest is BaseTest { CapabilityRegistry.Node memory node = s_capabilityRegistry.getNode(P2P_ID); assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); assertEq(node.p2pId, P2P_ID); - assertEq(node.supportedCapabilityIds.length, 2); - assertEq(node.supportedCapabilityIds[0], s_basicCapabilityId); - assertEq(node.supportedCapabilityIds[1], s_capabilityWithConfigurationContractId); + assertEq(node.supportedHashedCapabilityIds.length, 2); + assertEq(node.supportedHashedCapabilityIds[0], s_basicHashedCapabilityId); + assertEq(node.supportedHashedCapabilityIds[1], s_capabilityWithConfigurationContractId); } } diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_DeprecateCapability.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_DeprecateCapability.t.sol index 2e64ab7411f..b2f67339767 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_DeprecateCapability.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_DeprecateCapability.t.sol @@ -6,7 +6,7 @@ import {BaseTest} from "./BaseTest.t.sol"; import {CapabilityRegistry} from "../CapabilityRegistry.sol"; contract CapabilityRegistry_AddCapabilityTest is BaseTest { - event CapabilityDeprecated(bytes32 indexed capabilityId); + event CapabilityDeprecated(bytes32 indexed hashedCapabilityId); function setUp() public override { BaseTest.setUp(); @@ -17,53 +17,55 @@ contract CapabilityRegistry_AddCapabilityTest is BaseTest { function test_RevertWhen_CalledByNonAdmin() public { changePrank(STRANGER); - bytes32 capabilityId = s_capabilityRegistry.getCapabilityID( - s_basicCapability.capabilityType, + bytes32 hashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId( + s_basicCapability.labelledName, s_basicCapability.version ); vm.expectRevert("Only callable by owner"); - s_capabilityRegistry.deprecateCapability(capabilityId); + s_capabilityRegistry.deprecateCapability(hashedCapabilityId); } function test_RevertWhen_CapabilityDoesNotExist() public { vm.expectRevert( - abi.encodeWithSelector(CapabilityRegistry.CapabilityDoesNotExist.selector, s_nonExistentCapabilityId) + abi.encodeWithSelector(CapabilityRegistry.CapabilityDoesNotExist.selector, s_nonExistentHashedCapabilityId) ); - s_capabilityRegistry.deprecateCapability(s_nonExistentCapabilityId); + s_capabilityRegistry.deprecateCapability(s_nonExistentHashedCapabilityId); } function test_RevertWhen_CapabilityAlreadyDeprecated() public { - bytes32 capabilityId = s_capabilityRegistry.getCapabilityID( - s_basicCapability.capabilityType, + bytes32 hashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId( + s_basicCapability.labelledName, s_basicCapability.version ); - s_capabilityRegistry.deprecateCapability(capabilityId); + s_capabilityRegistry.deprecateCapability(hashedCapabilityId); - vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.CapabilityAlreadyDeprecated.selector, capabilityId)); - s_capabilityRegistry.deprecateCapability(capabilityId); + vm.expectRevert( + abi.encodeWithSelector(CapabilityRegistry.CapabilityAlreadyDeprecated.selector, hashedCapabilityId) + ); + s_capabilityRegistry.deprecateCapability(hashedCapabilityId); } function test_DeprecatesCapability() public { - bytes32 capabilityId = s_capabilityRegistry.getCapabilityID( - s_basicCapability.capabilityType, + bytes32 hashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId( + s_basicCapability.labelledName, s_basicCapability.version ); - s_capabilityRegistry.deprecateCapability(capabilityId); + s_capabilityRegistry.deprecateCapability(hashedCapabilityId); - assertEq(s_capabilityRegistry.isCapabilityDeprecated(capabilityId), true); + assertEq(s_capabilityRegistry.isCapabilityDeprecated(hashedCapabilityId), true); } function test_EmitsEvent() public { - bytes32 capabilityId = s_capabilityRegistry.getCapabilityID( - s_basicCapability.capabilityType, + bytes32 hashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId( + s_basicCapability.labelledName, s_basicCapability.version ); vm.expectEmit(address(s_capabilityRegistry)); - emit CapabilityDeprecated(capabilityId); - s_capabilityRegistry.deprecateCapability(capabilityId); + emit CapabilityDeprecated(hashedCapabilityId); + s_capabilityRegistry.deprecateCapability(hashedCapabilityId); } } diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilities.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilities.t.sol index b14397ba4ef..010fb619ba8 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilities.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilities.t.sol @@ -17,12 +17,12 @@ contract CapabilityRegistry_GetCapabilitiesTest is BaseTest { assertEq(capabilities.length, 2); - assertEq(capabilities[0].capabilityType, "data-streams-reports"); + assertEq(capabilities[0].labelledName, "data-streams-reports"); assertEq(capabilities[0].version, "1.0.0"); assertEq(uint256(capabilities[0].responseType), uint256(CapabilityRegistry.CapabilityResponseType.REPORT)); assertEq(capabilities[0].configurationContract, address(0)); - assertEq(capabilities[1].capabilityType, "read-ethereum-mainnet-gas-price"); + assertEq(capabilities[1].labelledName, "read-ethereum-mainnet-gas-price"); assertEq(capabilities[1].version, "1.0.2"); assertEq( uint256(capabilities[1].responseType), @@ -32,16 +32,16 @@ contract CapabilityRegistry_GetCapabilitiesTest is BaseTest { } function test_ExcludesDeprecatedCapabilities() public { - bytes32 capabilityId = s_capabilityRegistry.getCapabilityID( - s_basicCapability.capabilityType, + bytes32 hashedCapabilityId = s_capabilityRegistry.getHashedCapabilityId( + s_basicCapability.labelledName, s_basicCapability.version ); - s_capabilityRegistry.deprecateCapability(capabilityId); + s_capabilityRegistry.deprecateCapability(hashedCapabilityId); CapabilityRegistry.Capability[] memory capabilities = s_capabilityRegistry.getCapabilities(); assertEq(capabilities.length, 1); - assertEq(capabilities[0].capabilityType, "read-ethereum-mainnet-gas-price"); + assertEq(capabilities[0].labelledName, "read-ethereum-mainnet-gas-price"); assertEq(capabilities[0].version, "1.0.2"); assertEq( uint256(capabilities[0].responseType), diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilityIds.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilityIds.t.sol index de7810b4c15..b3dc333f5c3 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilityIds.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_GetCapabilityIds.t.sol @@ -13,12 +13,12 @@ contract CapabilityRegistry_GetCapabilitiesTest is BaseTest { assertEq(capabilities.length, 2); - assertEq(capabilities[0].capabilityType, "data-streams-reports"); + assertEq(capabilities[0].labelledName, "data-streams-reports"); assertEq(capabilities[0].version, "1.0.0"); assertEq(uint256(capabilities[0].responseType), uint256(CapabilityRegistry.CapabilityResponseType.REPORT)); assertEq(capabilities[0].configurationContract, address(0)); - assertEq(capabilities[1].capabilityType, "read-ethereum-mainnet-gas-price"); + assertEq(capabilities[1].labelledName, "read-ethereum-mainnet-gas-price"); assertEq(capabilities[1].version, "1.0.2"); assertEq( uint256(capabilities[1].responseType), diff --git a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go index b54a101d44e..8ea5e29d99c 100644 --- a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go +++ b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go @@ -31,17 +31,17 @@ var ( ) type CapabilityRegistryCapability struct { - CapabilityType [32]byte + LabelledName [32]byte Version [32]byte ResponseType uint8 ConfigurationContract common.Address } type CapabilityRegistryNode struct { - NodeOperatorId *big.Int - P2pId [32]byte - Signer common.Address - SupportedCapabilityIds [][32]byte + NodeOperatorId *big.Int + P2pId [32]byte + Signer common.Address + SupportedHashedCapabilityIds [][32]byte } type CapabilityRegistryNodeOperator struct { @@ -50,8 +50,8 @@ type CapabilityRegistryNodeOperator struct { } var CapabilityRegistryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAlreadyDeprecated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"capabilityIds\",\"type\":\"bytes32[]\"}],\"name\":\"InvalidNodeCapabilities\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"InvalidNodeP2PId\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"lengthOne\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lengthTwo\",\"type\":\"uint256\"}],\"name\":\"LengthMismatch\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDeprecated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"addNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"deprecateCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilities\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityID\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"getNode\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"isCapabilityDeprecated\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"updateNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60806040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000a5565b50505062000150565b336001600160a01b03821603620000ff5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61214580620001606000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c806365c14dc711610097578063ae3c241c11610066578063ae3c241c14610292578063c2d483a1146102a5578063ddbe4f82146102b8578063f2fde38b146102cd57600080fd5b806365c14dc71461022257806379ba5097146102425780638da5cb5b1461024a5780639cb7c5f41461027257600080fd5b80631cdf6343116100d35780631cdf634314610194578063229111f5146101a7578063398f3773146101ef57806350c946fe1461020257600080fd5b80630c5801e314610105578063117392ce1461011a578063125700111461012d578063181f5a7714610155575b600080fd5b6101186101133660046116ec565b6102e0565b005b610118610128366004611758565b6105f1565b61014061013b366004611770565b61083c565b60405190151581526020015b60405180910390f35b604080518082018252601881527f4361706162696c697479526567697374727920312e302e3000000000000000006020820152905161014c91906117ed565b6101186101a2366004611800565b61084f565b6101e16101b5366004611842565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b60405190815260200161014c565b6101186101fd366004611800565b610912565b610215610210366004611770565b610aab565b60405161014c9190611864565b610235610230366004611770565b610b73565b60405161014c91906118ea565b610118610c50565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b610285610280366004611770565b610d4d565b60405161014c91906119cc565b6101186102a0366004611770565b610df7565b6101186102b3366004611800565b610ec2565b6102c061124c565b60405161014c91906119da565b6101186102db366004611a4a565b611391565b828114610328576040517fab8b67c600000000000000000000000000000000000000000000000000000000815260048101849052602481018290526044015b60405180910390fd5b6000805473ffffffffffffffffffffffffffffffffffffffff16905b848110156105e957600086868381811061036057610360611a67565b905060200201359050600085858481811061037d5761037d611a67565b905060200281019061038f9190611a96565b61039890611b9e565b805190915073ffffffffffffffffffffffffffffffffffffffff166103e9576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16331480159061042657503373ffffffffffffffffffffffffffffffffffffffff851614155b1561045d576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160008381526007602052604090205473ffffffffffffffffffffffffffffffffffffffff908116911614158061050f57506020808201516040516104a392016117ed565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206000868152600783529290922091926104f6926001019101611cb7565b6040516020818303038152906040528051906020012014155b156105d6578051600083815260076020908152604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90931692909217825582015160019091019061057c9082611da6565b50806000015173ffffffffffffffffffffffffffffffffffffffff167f14c8f513e8a6d86d2d16b0cb64976de4e72386c4f8068eca3b7354373f8fe97a8383602001516040516105cd929190611ec0565b60405180910390a25b5050806105e290611f08565b9050610344565b505050505050565b6105f96113a5565b604080518235602082810191909152808401358284015282518083038401815260609092019092528051910120610631600382611428565b15610668576040517fe288638f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061067a6080840160608501611a4a565b73ffffffffffffffffffffffffffffffffffffffff16146107e5576106a56080830160608401611a4a565b73ffffffffffffffffffffffffffffffffffffffff163b158061078557506106d36080830160608401611a4a565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f884efe6100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff91909116906301ffc9a790602401602060405180830381865afa15801561075f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107839190611f40565b155b156107e55761079a6080830160608401611a4a565b6040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161031f565b6107f0600382611443565b506000818152600260205260409020829061080b8282611f62565b505060405181907f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff0690600090a25050565b6000610849600583611428565b92915050565b6108576113a5565b60005b8181101561090d57600083838381811061087657610876611a67565b60209081029290920135600081815260079093526040832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559093509190506108c76001830182611606565b50506040518181527f1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f9060200160405180910390a15061090681611f08565b905061085a565b505050565b61091a6113a5565b60005b8181101561090d57600083838381811061093957610939611a67565b905060200281019061094b9190611a96565b61095490611b9e565b805190915073ffffffffffffffffffffffffffffffffffffffff166109a5576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600954604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526007909252939020825181547fffffffffffffffffffffffff000000000000000000000000000000000000000016921691909117815591519091906001820190610a289082611da6565b50905050600960008154610a3b90611f08565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b91610a9091859190611ec0565b60405180910390a2505080610aa490611f08565b905061091d565b6040805160808101825260008082526020820181905291810191909152606080820152600082815260086020908152604091829020825160808101845281548152600182015481840152600282015473ffffffffffffffffffffffffffffffffffffffff16818501526003820180548551818602810186019096528086529194929360608601939290830182828015610b6357602002820191906000526020600020905b815481526020019060010190808311610b4f575b5050505050815250509050919050565b6040805180820190915260008152606060208201526000828152600760209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610bd090611c6a565b80601f0160208091040260200160405190810160405280929190818152602001828054610bfc90611c6a565b8015610b635780601f10610c1e57610100808354040283529160200191610b63565b820191906000526020600020905b815481529060010190602001808311610c2c57505050919092525091949350505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610cd1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161031f565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b604080516080808201835260008083526020808401829052838501829052606084018290528582526002808252918590208551938401865280548452600180820154928501929092529182015493949293919284019160ff1690811115610db657610db661192d565b6001811115610dc757610dc761192d565b815260029190910154610100900473ffffffffffffffffffffffffffffffffffffffff1660209091015292915050565b610dff6113a5565b610e0a600382611428565b610e43576040517fe181733f0000000000000000000000000000000000000000000000000000000081526004810182905260240161031f565b610e4e600582611428565b15610e88576040517f16950d1d0000000000000000000000000000000000000000000000000000000081526004810182905260240161031f565b610e93600582611443565b5060405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf2190600090a250565b60005b8181101561090d576000838383818110610ee157610ee1611a67565b9050602002810190610ef39190611fe4565b610efc90612018565b805160009081526007602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff168252600181018054959650939491939092840191610f4c90611c6a565b80601f0160208091040260200160405190810160405280929190818152602001828054610f7890611c6a565b8015610fc55780601f10610f9a57610100808354040283529160200191610fc5565b820191906000526020600020905b815481529060010190602001808311610fa857829003601f168201915b5050505050815250509050806000015173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611039576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020808301516000908152600890915260409020600301541515808061106157506020830151155b156110a05782602001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161031f91815260200190565b8260600151516000036110e55782606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161031f91906120ed565b60005b836060015151811015611172576111268460600151828151811061110e5761110e611a67565b6020026020010151600361142890919063ffffffff16565b6111625783606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161031f91906120ed565b61116b81611f08565b90506110e8565b506020838101805160009081526008835260409081902086518155915160018301558501516002820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9092169190911790556060850151805186936111f7926003850192910190611640565b505050602083810151845160408051928352928201527f5bfe8a52ad26ac6ee7b0cd46d2fd92be04735a31c45ef8aa3d4b7ea1b61bbc1f910160405180910390a15050508061124590611f08565b9050610ec5565b6060600061125a600361144f565b90506000611268600561145c565b82516112749190612125565b67ffffffffffffffff81111561128c5761128c611ad4565b6040519080825280602002602001820160405280156112fc57816020015b6040805160808101825260008082526020808301829052928201819052606082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816112aa5790505b5090506000805b835181101561138857600084828151811061132057611320611a67565b6020026020010151905061133e81600561142890919063ffffffff16565b6113775761134b81610d4d565b84848151811061135d5761135d611a67565b6020026020010181905250828061137390611f08565b9350505b5061138181611f08565b9050611303565b50909392505050565b6113996113a5565b6113a281611466565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314611426576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161031f565b565b600081815260018301602052604081205415155b9392505050565b600061143c838361155b565b6060600061143c836115aa565b6000610849825490565b3373ffffffffffffffffffffffffffffffffffffffff8216036114e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161031f565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120546115a257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610849565b506000610849565b6060816000018054806020026020016040519081016040528092919081815260200182805480156115fa57602002820191906000526020600020905b8154815260200190600101908083116115e6575b50505050509050919050565b50805461161290611c6a565b6000825580601f10611622575050565b601f0160209004906000526020600020908101906113a2919061168b565b82805482825590600052602060002090810192821561167b579160200282015b8281111561167b578251825591602001919060010190611660565b5061168792915061168b565b5090565b5b80821115611687576000815560010161168c565b60008083601f8401126116b257600080fd5b50813567ffffffffffffffff8111156116ca57600080fd5b6020830191508360208260051b85010111156116e557600080fd5b9250929050565b6000806000806040858703121561170257600080fd5b843567ffffffffffffffff8082111561171a57600080fd5b611726888389016116a0565b9096509450602087013591508082111561173f57600080fd5b5061174c878288016116a0565b95989497509550505050565b60006080828403121561176a57600080fd5b50919050565b60006020828403121561178257600080fd5b5035919050565b6000815180845260005b818110156117af57602081850181015186830182015201611793565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061143c6020830184611789565b6000806020838503121561181357600080fd5b823567ffffffffffffffff81111561182a57600080fd5b611836858286016116a0565b90969095509350505050565b6000806040838503121561185557600080fd5b50508035926020909101359150565b6000602080835260a0830184518285015281850151604085015273ffffffffffffffffffffffffffffffffffffffff6040860151166060850152606085015160808086015281815180845260c0870191508483019350600092505b808310156118df57835182529284019260019290920191908401906118bf565b509695505050505050565b6020815273ffffffffffffffffffffffffffffffffffffffff8251166020820152600060208301516040808401526119256060840182611789565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b80518252602081015160208301526040810151600281106119a6577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b604083015260609081015173ffffffffffffffffffffffffffffffffffffffff16910152565b60808101610849828461195c565b6020808252825182820181905260009190848201906040850190845b81811015611a1c57611a0983855161195c565b92840192608092909201916001016119f6565b50909695505050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146113a257600080fd5b600060208284031215611a5c57600080fd5b813561143c81611a28565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112611aca57600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611b2657611b26611ad4565b60405290565b6040516080810167ffffffffffffffff81118282101715611b2657611b26611ad4565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611b9657611b96611ad4565b604052919050565b600060408236031215611bb057600080fd5b611bb8611b03565b8235611bc381611a28565b815260208381013567ffffffffffffffff80821115611be157600080fd5b9085019036601f830112611bf457600080fd5b813581811115611c0657611c06611ad4565b611c36847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611b4f565b91508082523684828501011115611c4c57600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c90821680611c7e57607f821691505b60208210810361176a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454611ccb81611c6a565b80848701526040600180841660008114611cec5760018114611d2457611d52565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a01019550611d52565b896000528660002060005b85811015611d4a5781548b8201860152908301908801611d2f565b8a0184019650505b509398975050505050505050565b601f82111561090d57600081815260208120601f850160051c81016020861015611d875750805b601f850160051c820191505b818110156105e957828155600101611d93565b815167ffffffffffffffff811115611dc057611dc0611ad4565b611dd481611dce8454611c6a565b84611d60565b602080601f831160018114611e275760008415611df15750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556105e9565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015611e7457888601518255948401946001909101908401611e55565b5085821015611eb057878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8281526040602082015260006119256040830184611789565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611f3957611f39611ed9565b5060010190565b600060208284031215611f5257600080fd5b8151801515811461143c57600080fd5b813581556020820135600182015560028101604083013560028110611f8657600080fd5b81546060850135611f9681611a28565b74ffffffffffffffffffffffffffffffffffffffff008160081b1660ff84167fffffffffffffffffffffff000000000000000000000000000000000000000000841617178455505050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112611aca57600080fd5b60006080823603121561202a57600080fd5b612032611b2c565b8235815260208084013581830152604084013561204e81611a28565b6040830152606084013567ffffffffffffffff8082111561206e57600080fd5b9085019036601f83011261208157600080fd5b81358181111561209357612093611ad4565b8060051b91506120a4848301611b4f565b81815291830184019184810190368411156120be57600080fd5b938501935b838510156120dc578435825293850193908501906120c3565b606087015250939695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015611a1c57835183529284019291840191600101612109565b8181038181111561084957610849611ed956fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAlreadyDeprecated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"name\":\"InvalidNodeCapabilities\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"InvalidNodeP2PId\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"lengthOne\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lengthTwo\",\"type\":\"uint256\"}],\"name\":\"LengthMismatch\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDeprecated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedHashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"addNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"deprecateCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilities\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedId\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getHashedCapabilityId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"getNode\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedHashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"isCapabilityDeprecated\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"updateNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60806040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000a5565b50505062000150565b336001600160a01b03821603620000ff5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61214580620001606000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c806365c14dc711610097578063ae3c241c11610066578063ae3c241c14610292578063c2d483a1146102a5578063ddbe4f82146102b8578063f2fde38b146102cd57600080fd5b806365c14dc71461022257806379ba5097146102425780638da5cb5b1461024a5780639cb7c5f41461027257600080fd5b80631cdf6343116100d35780631cdf63431461019457806336b402fb146101a7578063398f3773146101ef57806350c946fe1461020257600080fd5b80630c5801e314610105578063117392ce1461011a578063125700111461012d578063181f5a7714610155575b600080fd5b6101186101133660046116ec565b6102e0565b005b610118610128366004611758565b6105f1565b61014061013b366004611770565b61083c565b60405190151581526020015b60405180910390f35b604080518082018252601881527f4361706162696c697479526567697374727920312e302e3000000000000000006020820152905161014c91906117ed565b6101186101a2366004611800565b61084f565b6101e16101b5366004611842565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b60405190815260200161014c565b6101186101fd366004611800565b610912565b610215610210366004611770565b610aab565b60405161014c9190611864565b610235610230366004611770565b610b73565b60405161014c91906118ea565b610118610c50565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b610285610280366004611770565b610d4d565b60405161014c91906119cc565b6101186102a0366004611770565b610df7565b6101186102b3366004611800565b610ec2565b6102c061124c565b60405161014c91906119da565b6101186102db366004611a4a565b611391565b828114610328576040517fab8b67c600000000000000000000000000000000000000000000000000000000815260048101849052602481018290526044015b60405180910390fd5b6000805473ffffffffffffffffffffffffffffffffffffffff16905b848110156105e957600086868381811061036057610360611a67565b905060200201359050600085858481811061037d5761037d611a67565b905060200281019061038f9190611a96565b61039890611b9e565b805190915073ffffffffffffffffffffffffffffffffffffffff166103e9576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16331480159061042657503373ffffffffffffffffffffffffffffffffffffffff851614155b1561045d576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160008381526007602052604090205473ffffffffffffffffffffffffffffffffffffffff908116911614158061050f57506020808201516040516104a392016117ed565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206000868152600783529290922091926104f6926001019101611cb7565b6040516020818303038152906040528051906020012014155b156105d6578051600083815260076020908152604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90931692909217825582015160019091019061057c9082611da6565b50806000015173ffffffffffffffffffffffffffffffffffffffff167f14c8f513e8a6d86d2d16b0cb64976de4e72386c4f8068eca3b7354373f8fe97a8383602001516040516105cd929190611ec0565b60405180910390a25b5050806105e290611f08565b9050610344565b505050505050565b6105f96113a5565b604080518235602082810191909152808401358284015282518083038401815260609092019092528051910120610631600382611428565b15610668576040517fe288638f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061067a6080840160608501611a4a565b73ffffffffffffffffffffffffffffffffffffffff16146107e5576106a56080830160608401611a4a565b73ffffffffffffffffffffffffffffffffffffffff163b158061078557506106d36080830160608401611a4a565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f884efe6100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff91909116906301ffc9a790602401602060405180830381865afa15801561075f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107839190611f40565b155b156107e55761079a6080830160608401611a4a565b6040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161031f565b6107f0600382611443565b506000818152600260205260409020829061080b8282611f62565b505060405181907f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff0690600090a25050565b6000610849600583611428565b92915050565b6108576113a5565b60005b8181101561090d57600083838381811061087657610876611a67565b60209081029290920135600081815260079093526040832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559093509190506108c76001830182611606565b50506040518181527f1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f9060200160405180910390a15061090681611f08565b905061085a565b505050565b61091a6113a5565b60005b8181101561090d57600083838381811061093957610939611a67565b905060200281019061094b9190611a96565b61095490611b9e565b805190915073ffffffffffffffffffffffffffffffffffffffff166109a5576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600954604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526007909252939020825181547fffffffffffffffffffffffff000000000000000000000000000000000000000016921691909117815591519091906001820190610a289082611da6565b50905050600960008154610a3b90611f08565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b91610a9091859190611ec0565b60405180910390a2505080610aa490611f08565b905061091d565b6040805160808101825260008082526020820181905291810191909152606080820152600082815260086020908152604091829020825160808101845281548152600182015481840152600282015473ffffffffffffffffffffffffffffffffffffffff16818501526003820180548551818602810186019096528086529194929360608601939290830182828015610b6357602002820191906000526020600020905b815481526020019060010190808311610b4f575b5050505050815250509050919050565b6040805180820190915260008152606060208201526000828152600760209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610bd090611c6a565b80601f0160208091040260200160405190810160405280929190818152602001828054610bfc90611c6a565b8015610b635780601f10610c1e57610100808354040283529160200191610b63565b820191906000526020600020905b815481529060010190602001808311610c2c57505050919092525091949350505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610cd1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161031f565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b604080516080808201835260008083526020808401829052838501829052606084018290528582526002808252918590208551938401865280548452600180820154928501929092529182015493949293919284019160ff1690811115610db657610db661192d565b6001811115610dc757610dc761192d565b815260029190910154610100900473ffffffffffffffffffffffffffffffffffffffff1660209091015292915050565b610dff6113a5565b610e0a600382611428565b610e43576040517fe181733f0000000000000000000000000000000000000000000000000000000081526004810182905260240161031f565b610e4e600582611428565b15610e88576040517f16950d1d0000000000000000000000000000000000000000000000000000000081526004810182905260240161031f565b610e93600582611443565b5060405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf2190600090a250565b60005b8181101561090d576000838383818110610ee157610ee1611a67565b9050602002810190610ef39190611fe4565b610efc90612018565b805160009081526007602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff168252600181018054959650939491939092840191610f4c90611c6a565b80601f0160208091040260200160405190810160405280929190818152602001828054610f7890611c6a565b8015610fc55780601f10610f9a57610100808354040283529160200191610fc5565b820191906000526020600020905b815481529060010190602001808311610fa857829003601f168201915b5050505050815250509050806000015173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611039576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020808301516000908152600890915260409020600301541515808061106157506020830151155b156110a05782602001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161031f91815260200190565b8260600151516000036110e55782606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161031f91906120ed565b60005b836060015151811015611172576111268460600151828151811061110e5761110e611a67565b6020026020010151600361142890919063ffffffff16565b6111625783606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161031f91906120ed565b61116b81611f08565b90506110e8565b506020838101805160009081526008835260409081902086518155915160018301558501516002820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9092169190911790556060850151805186936111f7926003850192910190611640565b505050602083810151845160408051928352928201527f5bfe8a52ad26ac6ee7b0cd46d2fd92be04735a31c45ef8aa3d4b7ea1b61bbc1f910160405180910390a15050508061124590611f08565b9050610ec5565b6060600061125a600361144f565b90506000611268600561145c565b82516112749190612125565b67ffffffffffffffff81111561128c5761128c611ad4565b6040519080825280602002602001820160405280156112fc57816020015b6040805160808101825260008082526020808301829052928201819052606082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816112aa5790505b5090506000805b835181101561138857600084828151811061132057611320611a67565b6020026020010151905061133e81600561142890919063ffffffff16565b6113775761134b81610d4d565b84848151811061135d5761135d611a67565b6020026020010181905250828061137390611f08565b9350505b5061138181611f08565b9050611303565b50909392505050565b6113996113a5565b6113a281611466565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314611426576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161031f565b565b600081815260018301602052604081205415155b9392505050565b600061143c838361155b565b6060600061143c836115aa565b6000610849825490565b3373ffffffffffffffffffffffffffffffffffffffff8216036114e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161031f565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120546115a257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610849565b506000610849565b6060816000018054806020026020016040519081016040528092919081815260200182805480156115fa57602002820191906000526020600020905b8154815260200190600101908083116115e6575b50505050509050919050565b50805461161290611c6a565b6000825580601f10611622575050565b601f0160209004906000526020600020908101906113a2919061168b565b82805482825590600052602060002090810192821561167b579160200282015b8281111561167b578251825591602001919060010190611660565b5061168792915061168b565b5090565b5b80821115611687576000815560010161168c565b60008083601f8401126116b257600080fd5b50813567ffffffffffffffff8111156116ca57600080fd5b6020830191508360208260051b85010111156116e557600080fd5b9250929050565b6000806000806040858703121561170257600080fd5b843567ffffffffffffffff8082111561171a57600080fd5b611726888389016116a0565b9096509450602087013591508082111561173f57600080fd5b5061174c878288016116a0565b95989497509550505050565b60006080828403121561176a57600080fd5b50919050565b60006020828403121561178257600080fd5b5035919050565b6000815180845260005b818110156117af57602081850181015186830182015201611793565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061143c6020830184611789565b6000806020838503121561181357600080fd5b823567ffffffffffffffff81111561182a57600080fd5b611836858286016116a0565b90969095509350505050565b6000806040838503121561185557600080fd5b50508035926020909101359150565b6000602080835260a0830184518285015281850151604085015273ffffffffffffffffffffffffffffffffffffffff6040860151166060850152606085015160808086015281815180845260c0870191508483019350600092505b808310156118df57835182529284019260019290920191908401906118bf565b509695505050505050565b6020815273ffffffffffffffffffffffffffffffffffffffff8251166020820152600060208301516040808401526119256060840182611789565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b80518252602081015160208301526040810151600281106119a6577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b604083015260609081015173ffffffffffffffffffffffffffffffffffffffff16910152565b60808101610849828461195c565b6020808252825182820181905260009190848201906040850190845b81811015611a1c57611a0983855161195c565b92840192608092909201916001016119f6565b50909695505050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146113a257600080fd5b600060208284031215611a5c57600080fd5b813561143c81611a28565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112611aca57600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611b2657611b26611ad4565b60405290565b6040516080810167ffffffffffffffff81118282101715611b2657611b26611ad4565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611b9657611b96611ad4565b604052919050565b600060408236031215611bb057600080fd5b611bb8611b03565b8235611bc381611a28565b815260208381013567ffffffffffffffff80821115611be157600080fd5b9085019036601f830112611bf457600080fd5b813581811115611c0657611c06611ad4565b611c36847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611b4f565b91508082523684828501011115611c4c57600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c90821680611c7e57607f821691505b60208210810361176a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454611ccb81611c6a565b80848701526040600180841660008114611cec5760018114611d2457611d52565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a01019550611d52565b896000528660002060005b85811015611d4a5781548b8201860152908301908801611d2f565b8a0184019650505b509398975050505050505050565b601f82111561090d57600081815260208120601f850160051c81016020861015611d875750805b601f850160051c820191505b818110156105e957828155600101611d93565b815167ffffffffffffffff811115611dc057611dc0611ad4565b611dd481611dce8454611c6a565b84611d60565b602080601f831160018114611e275760008415611df15750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556105e9565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015611e7457888601518255948401946001909101908401611e55565b5085821015611eb057878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8281526040602082015260006119256040830184611789565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611f3957611f39611ed9565b5060010190565b600060208284031215611f5257600080fd5b8151801515811461143c57600080fd5b813581556020820135600182015560028101604083013560028110611f8657600080fd5b81546060850135611f9681611a28565b74ffffffffffffffffffffffffffffffffffffffff008160081b1660ff84167fffffffffffffffffffffff000000000000000000000000000000000000000000841617178455505050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112611aca57600080fd5b60006080823603121561202a57600080fd5b612032611b2c565b8235815260208084013581830152604084013561204e81611a28565b6040830152606084013567ffffffffffffffff8082111561206e57600080fd5b9085019036601f83011261208157600080fd5b81358181111561209357612093611ad4565b8060051b91506120a4848301611b4f565b81815291830184019184810190368411156120be57600080fd5b938501935b838510156120dc578435825293850193908501906120c3565b606087015250939695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015611a1c57835183529284019291840191600101612109565b8181038181111561084957610849611ed956fea164736f6c6343000813000a", } var CapabilityRegistryABI = CapabilityRegistryMetaData.ABI @@ -212,9 +212,9 @@ func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapabilities() ([ return _CapabilityRegistry.Contract.GetCapabilities(&_CapabilityRegistry.CallOpts) } -func (_CapabilityRegistry *CapabilityRegistryCaller) GetCapability(opts *bind.CallOpts, capabilityID [32]byte) (CapabilityRegistryCapability, error) { +func (_CapabilityRegistry *CapabilityRegistryCaller) GetCapability(opts *bind.CallOpts, hashedId [32]byte) (CapabilityRegistryCapability, error) { var out []interface{} - err := _CapabilityRegistry.contract.Call(opts, &out, "getCapability", capabilityID) + err := _CapabilityRegistry.contract.Call(opts, &out, "getCapability", hashedId) if err != nil { return *new(CapabilityRegistryCapability), err @@ -226,17 +226,17 @@ func (_CapabilityRegistry *CapabilityRegistryCaller) GetCapability(opts *bind.Ca } -func (_CapabilityRegistry *CapabilityRegistrySession) GetCapability(capabilityID [32]byte) (CapabilityRegistryCapability, error) { - return _CapabilityRegistry.Contract.GetCapability(&_CapabilityRegistry.CallOpts, capabilityID) +func (_CapabilityRegistry *CapabilityRegistrySession) GetCapability(hashedId [32]byte) (CapabilityRegistryCapability, error) { + return _CapabilityRegistry.Contract.GetCapability(&_CapabilityRegistry.CallOpts, hashedId) } -func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapability(capabilityID [32]byte) (CapabilityRegistryCapability, error) { - return _CapabilityRegistry.Contract.GetCapability(&_CapabilityRegistry.CallOpts, capabilityID) +func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapability(hashedId [32]byte) (CapabilityRegistryCapability, error) { + return _CapabilityRegistry.Contract.GetCapability(&_CapabilityRegistry.CallOpts, hashedId) } -func (_CapabilityRegistry *CapabilityRegistryCaller) GetCapabilityID(opts *bind.CallOpts, capabilityType [32]byte, version [32]byte) ([32]byte, error) { +func (_CapabilityRegistry *CapabilityRegistryCaller) GetHashedCapabilityId(opts *bind.CallOpts, labelledName [32]byte, version [32]byte) ([32]byte, error) { var out []interface{} - err := _CapabilityRegistry.contract.Call(opts, &out, "getCapabilityID", capabilityType, version) + err := _CapabilityRegistry.contract.Call(opts, &out, "getHashedCapabilityId", labelledName, version) if err != nil { return *new([32]byte), err @@ -248,12 +248,12 @@ func (_CapabilityRegistry *CapabilityRegistryCaller) GetCapabilityID(opts *bind. } -func (_CapabilityRegistry *CapabilityRegistrySession) GetCapabilityID(capabilityType [32]byte, version [32]byte) ([32]byte, error) { - return _CapabilityRegistry.Contract.GetCapabilityID(&_CapabilityRegistry.CallOpts, capabilityType, version) +func (_CapabilityRegistry *CapabilityRegistrySession) GetHashedCapabilityId(labelledName [32]byte, version [32]byte) ([32]byte, error) { + return _CapabilityRegistry.Contract.GetHashedCapabilityId(&_CapabilityRegistry.CallOpts, labelledName, version) } -func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapabilityID(capabilityType [32]byte, version [32]byte) ([32]byte, error) { - return _CapabilityRegistry.Contract.GetCapabilityID(&_CapabilityRegistry.CallOpts, capabilityType, version) +func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetHashedCapabilityId(labelledName [32]byte, version [32]byte) ([32]byte, error) { + return _CapabilityRegistry.Contract.GetHashedCapabilityId(&_CapabilityRegistry.CallOpts, labelledName, version) } func (_CapabilityRegistry *CapabilityRegistryCaller) GetNode(opts *bind.CallOpts, p2pId [32]byte) (CapabilityRegistryNode, error) { @@ -300,9 +300,9 @@ func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetNodeOperator(node return _CapabilityRegistry.Contract.GetNodeOperator(&_CapabilityRegistry.CallOpts, nodeOperatorId) } -func (_CapabilityRegistry *CapabilityRegistryCaller) IsCapabilityDeprecated(opts *bind.CallOpts, capabilityId [32]byte) (bool, error) { +func (_CapabilityRegistry *CapabilityRegistryCaller) IsCapabilityDeprecated(opts *bind.CallOpts, hashedCapabilityId [32]byte) (bool, error) { var out []interface{} - err := _CapabilityRegistry.contract.Call(opts, &out, "isCapabilityDeprecated", capabilityId) + err := _CapabilityRegistry.contract.Call(opts, &out, "isCapabilityDeprecated", hashedCapabilityId) if err != nil { return *new(bool), err @@ -314,12 +314,12 @@ func (_CapabilityRegistry *CapabilityRegistryCaller) IsCapabilityDeprecated(opts } -func (_CapabilityRegistry *CapabilityRegistrySession) IsCapabilityDeprecated(capabilityId [32]byte) (bool, error) { - return _CapabilityRegistry.Contract.IsCapabilityDeprecated(&_CapabilityRegistry.CallOpts, capabilityId) +func (_CapabilityRegistry *CapabilityRegistrySession) IsCapabilityDeprecated(hashedCapabilityId [32]byte) (bool, error) { + return _CapabilityRegistry.Contract.IsCapabilityDeprecated(&_CapabilityRegistry.CallOpts, hashedCapabilityId) } -func (_CapabilityRegistry *CapabilityRegistryCallerSession) IsCapabilityDeprecated(capabilityId [32]byte) (bool, error) { - return _CapabilityRegistry.Contract.IsCapabilityDeprecated(&_CapabilityRegistry.CallOpts, capabilityId) +func (_CapabilityRegistry *CapabilityRegistryCallerSession) IsCapabilityDeprecated(hashedCapabilityId [32]byte) (bool, error) { + return _CapabilityRegistry.Contract.IsCapabilityDeprecated(&_CapabilityRegistry.CallOpts, hashedCapabilityId) } func (_CapabilityRegistry *CapabilityRegistryCaller) Owner(opts *bind.CallOpts) (common.Address, error) { @@ -414,16 +414,16 @@ func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AddNodes(nodes [ return _CapabilityRegistry.Contract.AddNodes(&_CapabilityRegistry.TransactOpts, nodes) } -func (_CapabilityRegistry *CapabilityRegistryTransactor) DeprecateCapability(opts *bind.TransactOpts, capabilityId [32]byte) (*types.Transaction, error) { - return _CapabilityRegistry.contract.Transact(opts, "deprecateCapability", capabilityId) +func (_CapabilityRegistry *CapabilityRegistryTransactor) DeprecateCapability(opts *bind.TransactOpts, hashedCapabilityId [32]byte) (*types.Transaction, error) { + return _CapabilityRegistry.contract.Transact(opts, "deprecateCapability", hashedCapabilityId) } -func (_CapabilityRegistry *CapabilityRegistrySession) DeprecateCapability(capabilityId [32]byte) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.DeprecateCapability(&_CapabilityRegistry.TransactOpts, capabilityId) +func (_CapabilityRegistry *CapabilityRegistrySession) DeprecateCapability(hashedCapabilityId [32]byte) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.DeprecateCapability(&_CapabilityRegistry.TransactOpts, hashedCapabilityId) } -func (_CapabilityRegistry *CapabilityRegistryTransactorSession) DeprecateCapability(capabilityId [32]byte) (*types.Transaction, error) { - return _CapabilityRegistry.Contract.DeprecateCapability(&_CapabilityRegistry.TransactOpts, capabilityId) +func (_CapabilityRegistry *CapabilityRegistryTransactorSession) DeprecateCapability(hashedCapabilityId [32]byte) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.DeprecateCapability(&_CapabilityRegistry.TransactOpts, hashedCapabilityId) } func (_CapabilityRegistry *CapabilityRegistryTransactor) RemoveNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []*big.Int) (*types.Transaction, error) { @@ -523,32 +523,32 @@ func (it *CapabilityRegistryCapabilityAddedIterator) Close() error { } type CapabilityRegistryCapabilityAdded struct { - CapabilityId [32]byte - Raw types.Log + HashedCapabilityId [32]byte + Raw types.Log } -func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterCapabilityAdded(opts *bind.FilterOpts, capabilityId [][32]byte) (*CapabilityRegistryCapabilityAddedIterator, error) { +func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterCapabilityAdded(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilityRegistryCapabilityAddedIterator, error) { - var capabilityIdRule []interface{} - for _, capabilityIdItem := range capabilityId { - capabilityIdRule = append(capabilityIdRule, capabilityIdItem) + var hashedCapabilityIdRule []interface{} + for _, hashedCapabilityIdItem := range hashedCapabilityId { + hashedCapabilityIdRule = append(hashedCapabilityIdRule, hashedCapabilityIdItem) } - logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "CapabilityAdded", capabilityIdRule) + logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "CapabilityAdded", hashedCapabilityIdRule) if err != nil { return nil, err } return &CapabilityRegistryCapabilityAddedIterator{contract: _CapabilityRegistry.contract, event: "CapabilityAdded", logs: logs, sub: sub}, nil } -func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchCapabilityAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityAdded, capabilityId [][32]byte) (event.Subscription, error) { +func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchCapabilityAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityAdded, hashedCapabilityId [][32]byte) (event.Subscription, error) { - var capabilityIdRule []interface{} - for _, capabilityIdItem := range capabilityId { - capabilityIdRule = append(capabilityIdRule, capabilityIdItem) + var hashedCapabilityIdRule []interface{} + for _, hashedCapabilityIdItem := range hashedCapabilityId { + hashedCapabilityIdRule = append(hashedCapabilityIdRule, hashedCapabilityIdItem) } - logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "CapabilityAdded", capabilityIdRule) + logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "CapabilityAdded", hashedCapabilityIdRule) if err != nil { return nil, err } @@ -650,32 +650,32 @@ func (it *CapabilityRegistryCapabilityDeprecatedIterator) Close() error { } type CapabilityRegistryCapabilityDeprecated struct { - CapabilityId [32]byte - Raw types.Log + HashedCapabilityId [32]byte + Raw types.Log } -func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterCapabilityDeprecated(opts *bind.FilterOpts, capabilityId [][32]byte) (*CapabilityRegistryCapabilityDeprecatedIterator, error) { +func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterCapabilityDeprecated(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilityRegistryCapabilityDeprecatedIterator, error) { - var capabilityIdRule []interface{} - for _, capabilityIdItem := range capabilityId { - capabilityIdRule = append(capabilityIdRule, capabilityIdItem) + var hashedCapabilityIdRule []interface{} + for _, hashedCapabilityIdItem := range hashedCapabilityId { + hashedCapabilityIdRule = append(hashedCapabilityIdRule, hashedCapabilityIdItem) } - logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "CapabilityDeprecated", capabilityIdRule) + logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "CapabilityDeprecated", hashedCapabilityIdRule) if err != nil { return nil, err } return &CapabilityRegistryCapabilityDeprecatedIterator{contract: _CapabilityRegistry.contract, event: "CapabilityDeprecated", logs: logs, sub: sub}, nil } -func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchCapabilityDeprecated(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityDeprecated, capabilityId [][32]byte) (event.Subscription, error) { +func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchCapabilityDeprecated(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityDeprecated, hashedCapabilityId [][32]byte) (event.Subscription, error) { - var capabilityIdRule []interface{} - for _, capabilityIdItem := range capabilityId { - capabilityIdRule = append(capabilityIdRule, capabilityIdItem) + var hashedCapabilityIdRule []interface{} + for _, hashedCapabilityIdItem := range hashedCapabilityId { + hashedCapabilityIdRule = append(hashedCapabilityIdRule, hashedCapabilityIdItem) } - logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "CapabilityDeprecated", capabilityIdRule) + logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "CapabilityDeprecated", hashedCapabilityIdRule) if err != nil { return nil, err } @@ -1544,15 +1544,15 @@ func (_CapabilityRegistry *CapabilityRegistry) Address() common.Address { type CapabilityRegistryInterface interface { GetCapabilities(opts *bind.CallOpts) ([]CapabilityRegistryCapability, error) - GetCapability(opts *bind.CallOpts, capabilityID [32]byte) (CapabilityRegistryCapability, error) + GetCapability(opts *bind.CallOpts, hashedId [32]byte) (CapabilityRegistryCapability, error) - GetCapabilityID(opts *bind.CallOpts, capabilityType [32]byte, version [32]byte) ([32]byte, error) + GetHashedCapabilityId(opts *bind.CallOpts, labelledName [32]byte, version [32]byte) ([32]byte, error) GetNode(opts *bind.CallOpts, p2pId [32]byte) (CapabilityRegistryNode, error) GetNodeOperator(opts *bind.CallOpts, nodeOperatorId *big.Int) (CapabilityRegistryNodeOperator, error) - IsCapabilityDeprecated(opts *bind.CallOpts, capabilityId [32]byte) (bool, error) + IsCapabilityDeprecated(opts *bind.CallOpts, hashedCapabilityId [32]byte) (bool, error) Owner(opts *bind.CallOpts) (common.Address, error) @@ -1566,7 +1566,7 @@ type CapabilityRegistryInterface interface { AddNodes(opts *bind.TransactOpts, nodes []CapabilityRegistryNode) (*types.Transaction, error) - DeprecateCapability(opts *bind.TransactOpts, capabilityId [32]byte) (*types.Transaction, error) + DeprecateCapability(opts *bind.TransactOpts, hashedCapabilityId [32]byte) (*types.Transaction, error) RemoveNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []*big.Int) (*types.Transaction, error) @@ -1574,15 +1574,15 @@ type CapabilityRegistryInterface interface { UpdateNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []*big.Int, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) - FilterCapabilityAdded(opts *bind.FilterOpts, capabilityId [][32]byte) (*CapabilityRegistryCapabilityAddedIterator, error) + FilterCapabilityAdded(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilityRegistryCapabilityAddedIterator, error) - WatchCapabilityAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityAdded, capabilityId [][32]byte) (event.Subscription, error) + WatchCapabilityAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityAdded, hashedCapabilityId [][32]byte) (event.Subscription, error) ParseCapabilityAdded(log types.Log) (*CapabilityRegistryCapabilityAdded, error) - FilterCapabilityDeprecated(opts *bind.FilterOpts, capabilityId [][32]byte) (*CapabilityRegistryCapabilityDeprecatedIterator, error) + FilterCapabilityDeprecated(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilityRegistryCapabilityDeprecatedIterator, error) - WatchCapabilityDeprecated(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityDeprecated, capabilityId [][32]byte) (event.Subscription, error) + WatchCapabilityDeprecated(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityDeprecated, hashedCapabilityId [][32]byte) (event.Subscription, error) ParseCapabilityDeprecated(log types.Log) (*CapabilityRegistryCapabilityDeprecated, error) diff --git a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 3e0110cdee6..182c8da3f7e 100644 --- a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,4 +1,4 @@ GETH_VERSION: 1.13.8 forwarder: ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.bin b4c900aae9e022f01abbac7993d41f93912247613ac6270b0c4da4ef6f2016e3 -keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin b7d748b585d7cf1cf91e268b609613f77a8390d119e03d724b49c25fd2ea75e7 +keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin aeb366351d69f320c610419a3e09a991bd6ea75690778835eb8f6421d1277f44 ocr3_capability: ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.bin 9dcbdf55bd5729ba266148da3f17733eb592c871c2108ccca546618628fd9ad2 diff --git a/core/services/workflows/engine.go b/core/services/workflows/engine.go index 9629e845336..e405102e123 100644 --- a/core/services/workflows/engine.go +++ b/core/services/workflows/engine.go @@ -78,7 +78,7 @@ func (e *Engine) resolveWorkflowCapabilities(ctx context.Context) error { // triggersInitialized := true for _, t := range e.workflow.triggers { - tg, err := e.registry.GetTrigger(ctx, t.Type) + tg, err := e.registry.GetTrigger(ctx, t.ID) if err != nil { e.logger.Errorf("failed to get trigger capability: %s", err) // we don't immediately return here, since we want to retry all triggers @@ -123,16 +123,16 @@ func (e *Engine) initializeCapability(ctx context.Context, s *step) error { return nil } - cp, err := e.registry.Get(ctx, s.Type) + cp, err := e.registry.Get(ctx, s.ID) if err != nil { - return fmt.Errorf("failed to get capability with ref %s: %s", s.Type, err) + return fmt.Errorf("failed to get capability with ref %s: %s", s.ID, err) } // We configure actions, consensus and targets here, and // they all satisfy the `CallbackCapability` interface cc, ok := cp.(capabilities.CallbackCapability) if !ok { - return fmt.Errorf("could not coerce capability %s to CallbackCapability", s.Type) + return fmt.Errorf("could not coerce capability %s to CallbackCapability", s.ID) } if s.config == nil { @@ -275,7 +275,7 @@ func (e *Engine) registerTrigger(ctx context.Context, t *triggerCapability) erro } eventsCh, err := t.trigger.RegisterTrigger(ctx, triggerRegRequest) if err != nil { - return fmt.Errorf("failed to instantiate trigger %s, %s", t.Type, err) + return fmt.Errorf("failed to instantiate trigger %s, %s", t.ID, err) } go func() { diff --git a/core/services/workflows/engine_test.go b/core/services/workflows/engine_test.go index 3896f840ee8..ff4c5682129 100644 --- a/core/services/workflows/engine_test.go +++ b/core/services/workflows/engine_test.go @@ -19,7 +19,7 @@ import ( const hardcodedWorkflow = ` triggers: - - type: "mercury-trigger" + - id: "mercury-trigger" config: feedIds: - "0x1111111111111111111100000000000000000000000000000000000000000000" @@ -27,7 +27,7 @@ triggers: - "0x3333333333333333333300000000000000000000000000000000000000000000" consensus: - - type: "offchain_reporting" + - id: "offchain_reporting" ref: "evm_median" inputs: observations: @@ -49,14 +49,14 @@ consensus: abi: "mercury_reports bytes[]" targets: - - type: "write_polygon-testnet-mumbai" + - id: "write_polygon-testnet-mumbai" inputs: report: "$(evm_median.outputs.report)" config: address: "0x3F3554832c636721F1fD1822Ccca0354576741Ef" params: ["$(report)"] abi: "receive(report bytes)" - - type: "write_ethereum-testnet-sepolia" + - id: "write_ethereum-testnet-sepolia" inputs: report: "$(evm_median.outputs.report)" config: @@ -215,7 +215,7 @@ func TestEngineWithHardcodedWorkflow(t *testing.T) { const ( simpleWorkflow = ` triggers: - - type: "mercury-trigger" + - id: "mercury-trigger" config: feedlist: - "0x1111111111111111111100000000000000000000000000000000000000000000" # ETHUSD @@ -223,7 +223,7 @@ triggers: - "0x3333333333333333333300000000000000000000000000000000000000000000" # BTCUSD consensus: - - type: "offchain_reporting" + - id: "offchain_reporting" ref: "evm_median" inputs: observations: @@ -245,7 +245,7 @@ consensus: abi: "mercury_reports bytes[]" targets: - - type: "write_polygon-testnet-mumbai" + - id: "write_polygon-testnet-mumbai" inputs: report: "$(evm_median.outputs.report)" config: @@ -368,7 +368,7 @@ func TestEngine_ErrorsTheWorkflowIfAStepErrors(t *testing.T) { const ( multiStepWorkflow = ` triggers: - - type: "mercury-trigger" + - id: "mercury-trigger" config: feedlist: - "0x1111111111111111111100000000000000000000000000000000000000000000" # ETHUSD @@ -376,14 +376,14 @@ triggers: - "0x3333333333333333333300000000000000000000000000000000000000000000" # BTCUSD actions: - - type: "read_chain_action" + - id: "read_chain_action" ref: "read_chain_action" inputs: action: - "$(trigger.outputs)" consensus: - - type: "offchain_reporting" + - id: "offchain_reporting" ref: "evm_median" inputs: observations: @@ -406,7 +406,7 @@ consensus: abi: "mercury_reports bytes[]" targets: - - type: "write_polygon-testnet-mumbai" + - id: "write_polygon-testnet-mumbai" inputs: report: "$(evm_median.outputs.report)" config: diff --git a/core/services/workflows/models.go b/core/services/workflows/models.go index 92abf36d2c0..cd167403089 100644 --- a/core/services/workflows/models.go +++ b/core/services/workflows/models.go @@ -19,8 +19,7 @@ type stepRequest struct { // // Within the workflow spec, they are called "Capability Properties". type stepDefinition struct { - // TODO: Rename this, type here refers to the capability ID, not its type. - Type string `json:"type" jsonschema:"required"` + ID string `json:"id" jsonschema:"required"` Ref string `json:"ref,omitempty" jsonschema:"pattern=^[a-z0-9_]+$"` Inputs map[string]any `json:"inputs,omitempty"` Config map[string]any `json:"config" jsonschema:"required"` @@ -160,7 +159,7 @@ func Parse(yamlWorkflow string) (*workflow, error) { // To handle this, we default the `Ref` to the type, but ideally we // should find a better long-term way to handle this. if s.Ref == "" { - s.Ref = s.Type + s.Ref = s.ID } innerErr := g.AddVertex(&step{stepDefinition: s}) diff --git a/core/services/workflows/models_test.go b/core/services/workflows/models_test.go index 232e91eaaa8..0964b13d277 100644 --- a/core/services/workflows/models_test.go +++ b/core/services/workflows/models_test.go @@ -19,23 +19,23 @@ func TestParse_Graph(t *testing.T) { name: "basic example", yaml: ` triggers: - - type: "a-trigger" + - id: "a-trigger" actions: - - type: "an-action" + - id: "an-action" ref: "an-action" inputs: trigger_output: $(trigger.outputs) consensus: - - type: "a-consensus" + - id: "a-consensus" ref: "a-consensus" inputs: trigger_output: $(trigger.outputs) an-action_output: $(an-action.outputs) targets: - - type: "a-target" + - id: "a-target" ref: "a-target" inputs: consensus_output: $(a-consensus.outputs) @@ -58,28 +58,28 @@ targets: name: "circular relationship", yaml: ` triggers: - - type: "a-trigger" + - id: "a-trigger" actions: - - type: "an-action" + - id: "an-action" ref: "an-action" inputs: trigger_output: $(trigger.outputs) output: $(a-second-action.outputs) - - type: "a-second-action" + - id: "a-second-action" ref: "a-second-action" inputs: output: $(an-action.outputs) consensus: - - type: "a-consensus" + - id: "a-consensus" ref: "a-consensus" inputs: trigger_output: $(trigger.outputs) an-action_output: $(an-action.outputs) targets: - - type: "a-target" + - id: "a-target" ref: "a-target" inputs: consensus_output: $(a-consensus.outputs) @@ -90,32 +90,32 @@ targets: name: "indirect circular relationship", yaml: ` triggers: - - type: "a-trigger" + - id: "a-trigger" actions: - - type: "an-action" + - id: "an-action" ref: "an-action" inputs: trigger_output: $(trigger.outputs) action_output: $(a-third-action.outputs) - - type: "a-second-action" + - id: "a-second-action" ref: "a-second-action" inputs: output: $(an-action.outputs) - - type: "a-third-action" + - id: "a-third-action" ref: "a-third-action" inputs: output: $(a-second-action.outputs) consensus: - - type: "a-consensus" + - id: "a-consensus" ref: "a-consensus" inputs: trigger_output: $(trigger.outputs) an-action_output: $(an-action.outputs) targets: - - type: "a-target" + - id: "a-target" ref: "a-target" inputs: consensus_output: $(a-consensus.outputs) @@ -126,23 +126,23 @@ targets: name: "relationship doesn't exist", yaml: ` triggers: - - type: "a-trigger" + - id: "a-trigger" actions: - - type: "an-action" + - id: "an-action" ref: "an-action" inputs: trigger_output: $(trigger.outputs) action_output: $(missing-action.outputs) consensus: - - type: "a-consensus" + - id: "a-consensus" ref: "a-consensus" inputs: an-action_output: $(an-action.outputs) targets: - - type: "a-target" + - id: "a-target" ref: "a-target" inputs: consensus_output: $(a-consensus.outputs) @@ -153,23 +153,23 @@ targets: name: "two trigger nodes", yaml: ` triggers: - - type: "a-trigger" - - type: "a-second-trigger" + - id: "a-trigger" + - id: "a-second-trigger" actions: - - type: "an-action" + - id: "an-action" ref: "an-action" inputs: trigger_output: $(trigger.outputs) consensus: - - type: "a-consensus" + - id: "a-consensus" ref: "a-consensus" inputs: an-action_output: $(an-action.outputs) targets: - - type: "a-target" + - id: "a-target" ref: "a-target" inputs: consensus_output: $(a-consensus.outputs) @@ -191,21 +191,21 @@ targets: name: "non-trigger step with no dependent refs", yaml: ` triggers: - - type: "a-trigger" - - type: "a-second-trigger" + - id: "a-trigger" + - id: "a-second-trigger" actions: - - type: "an-action" + - id: "an-action" ref: "an-action" inputs: hello: "world" consensus: - - type: "a-consensus" + - id: "a-consensus" ref: "a-consensus" inputs: trigger_output: $(trigger.outputs) action_output: $(an-action.outputs) targets: - - type: "a-target" + - id: "a-target" ref: "a-target" inputs: consensus_output: $(a-consensus.outputs) diff --git a/core/services/workflows/models_yaml.go b/core/services/workflows/models_yaml.go index 280a895f1b8..5ed7941f84a 100644 --- a/core/services/workflows/models_yaml.go +++ b/core/services/workflows/models_yaml.go @@ -166,17 +166,19 @@ func (m mapping) MarshalJSON() ([]byte, error) { // It allows for multiple ways of defining a step, which we later // convert to a single representation, `stepDefinition`. type stepDefinitionYaml struct { - // A universally unique name for a capability will be defined under the “type” property. The uniqueness will, eventually, be enforced in the Capability Registry . Semver must be used to specify the version of the Capability at the end of the type field. Capability versions must be immutable. + // A universally unique name for a capability will be defined under the “id” property. The uniqueness will, eventually, be enforced in the Capability Registry. + // + // Semver must be used to specify the version of the Capability at the end of the id field. Capability versions must be immutable. // // Initially, we will require major versions. This will ease upgrades early on while we develop the infrastructure. // // Eventually, we might support minor version and specific version pins. This will allow workflow authors to have flexibility when selecting the version, and node operators will be able to determine when they should update their capabilities. // - // There are two ways to specify a type - using a string as a fully qualified ID or a structured table. When using a table, labels are ordered alphanumerically and joined into a string following a + // There are two ways to specify an id - using a string as a fully qualified ID or a structured table. When using a table, labels are ordered alphanumerically and joined into a string following a // {name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}@{version} // pattern. // - // The “type” supports [a-z0-9_-:] characters followed by an @ and [semver regex] at the end. + // The “id” supports [a-z0-9_-:] characters followed by an @ and [semver regex] at the end. // // Validation must throw an error if: // @@ -184,11 +186,11 @@ type stepDefinitionYaml struct { // (For Keystone only.) More specific than a major version is specified. // // Example (string) - // type: read_chain:chain_ethereum:network_mainnet@1 + // id: read_chain:chain_ethereum:network_mainnet@1 // // Example (table) // - // type: + // id: // name: read_chain // version: 1 // labels: @@ -196,7 +198,7 @@ type stepDefinitionYaml struct { // network: mainnet // // [semver regex]: https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string - Type stepDefinitionType `json:"type" jsonschema:"required"` + ID stepDefinitionID `json:"id" jsonschema:"required"` // Actions and Consensus capabilities have a required “ref” property that must be unique within a Workflow file (not universally) This property enables referencing outputs and is required because Actions and Consensus always need to be referenced in the following phases. Triggers can optionally specify if they need to be referenced. // @@ -213,7 +215,7 @@ type stepDefinitionYaml struct { // Capabilities can specify an additional optional ”inputs” property. It allows specifying a dependency on the result of one or more other capabilities. These are always runtime values that cannot be provided upfront. It takes a map of the argument name internal to the capability and an explicit reference to the values. // - // References are specified using the [type].[ref].[path_to_value] pattern. + // References are specified using the [id].[ref].[path_to_value] pattern. // // The interpolation of “inputs” is allowed // @@ -231,7 +233,7 @@ type stepDefinitionYaml struct { // // Example // targets: - // - type: write_polygon_mainnet@1 + // - id: write_polygon_mainnet@1 // inputs: // report: // - consensus.evm_median.outputs.report @@ -248,66 +250,66 @@ type stepDefinitionYaml struct { func (s stepDefinitionYaml) toStepDefinition() stepDefinition { return stepDefinition{ Ref: s.Ref, - Type: s.Type.String(), + ID: s.ID.String(), Inputs: s.Inputs, Config: s.Config, } } -// stepDefinitionType represents both the string and table representations of the "type" field in a stepDefinition. -type stepDefinitionType struct { - typeStr string - typeTable *stepDefinitionTableType +// stepDefinitionID represents both the string and table representations of the "id" field in a stepDefinition. +type stepDefinitionID struct { + idStr string + idTable *stepDefinitionTableID } -func (s stepDefinitionType) String() string { - if s.typeStr != "" { - return s.typeStr +func (s stepDefinitionID) String() string { + if s.idStr != "" { + return s.idStr } - return s.typeTable.String() + return s.idTable.String() } -func (s *stepDefinitionType) UnmarshalJSON(data []byte) error { +func (s *stepDefinitionID) UnmarshalJSON(data []byte) error { // Unmarshal the JSON data into a map to determine if it's a string or a table var m string err := json.Unmarshal(data, &m) if err == nil { - s.typeStr = m + s.idStr = m return nil } - // If the JSON data is a table, unmarshal it into a stepDefinitionTableType - var table stepDefinitionTableType + // If the JSON data is a table, unmarshal it into a stepDefinitionTableID + var table stepDefinitionTableID err = json.Unmarshal(data, &table) if err != nil { return err } - s.typeTable = &table + s.idTable = &table return nil } -func (s *stepDefinitionType) MarshalJSON() ([]byte, error) { - if s.typeStr != "" { - return json.Marshal(s.typeStr) +func (s *stepDefinitionID) MarshalJSON() ([]byte, error) { + if s.idStr != "" { + return json.Marshal(s.idStr) } - return json.Marshal(s.typeTable) + return json.Marshal(s.idTable) } -// JSONSchema returns the JSON schema for a stepDefinitionType. +// JSONSchema returns the JSON schema for a stepDefinitionID. // // The schema is a oneOf schema that allows either a string or a table. -func (stepDefinitionType) JSONSchema() *jsonschema.Schema { +func (stepDefinitionID) JSONSchema() *jsonschema.Schema { reflector := jsonschema.Reflector{DoNotReference: true, ExpandedStruct: true} - tableSchema := reflector.Reflect(&stepDefinitionTableType{}) + tableSchema := reflector.Reflect(&stepDefinitionTableID{}) stringSchema := &jsonschema.Schema{ - Type: "string", + ID: "string", Pattern: "^[a-z0-9_\\-:]+@(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$", } return &jsonschema.Schema{ - Title: "type", + Title: "id", OneOf: []*jsonschema.Schema{ stringSchema, tableSchema, @@ -315,21 +317,21 @@ func (stepDefinitionType) JSONSchema() *jsonschema.Schema { } } -// stepDefinitionTableType is the structured representation of a stepDefinitionType. -type stepDefinitionTableType struct { +// stepDefinitionTableID is the structured representation of a stepDefinitionID. +type stepDefinitionTableID struct { Name string `json:"name"` Version string `json:"version" jsonschema:"pattern=(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"` Labels map[string]string `json:"labels"` } -// String returns the string representation of a stepDefinitionTableType. +// String returns the string representation of a stepDefinitionTableID. // // It follows the format: // // {name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}@{version} // // where labels are ordered alphanumerically. -func (s stepDefinitionTableType) String() string { +func (s stepDefinitionTableID) String() string { labels := make([]string, 0, len(s.Labels)) for k, v := range s.Labels { labels = append(labels, fmt.Sprintf("%s_%s", k, v)) diff --git a/core/services/workflows/models_yaml_test.go b/core/services/workflows/models_yaml_test.go index 2732f1b44c7..efcdaf6f332 100644 --- a/core/services/workflows/models_yaml_test.go +++ b/core/services/workflows/models_yaml_test.go @@ -116,7 +116,7 @@ func TestWorkflowSpecMarshalling(t *testing.T) { } }) - t.Run("Table and string capability type", func(t *testing.T) { + t.Run("Table and string capability id", func(t *testing.T) { workflowBytes := fixtureReader("workflow_2") spec := workflowSpecYaml{} diff --git a/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_1.yaml b/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_1.yaml index cbd33f4a90e..9a9870af875 100644 --- a/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_1.yaml +++ b/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_1.yaml @@ -1,5 +1,5 @@ triggers: - - type: mercury-trigger@1 + - id: mercury-trigger@1 ref: report_data config: boolean_coercion: @@ -54,7 +54,7 @@ # no actions consensus: - - type: offchain_reporting@1 + - id: offchain_reporting@1 inputs: observations: - triggers.report_data.outputs @@ -76,7 +76,7 @@ abi: "mercury_reports bytes[]" targets: - - type: write_polygon_mainnet@1 + - id: write_polygon_mainnet@1 inputs: report: - consensus.evm_median.outputs.report diff --git a/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2.yaml b/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2.yaml index 50a598d0bc9..be40a91daa0 100644 --- a/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2.yaml +++ b/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2.yaml @@ -1,12 +1,12 @@ triggers: - - type: on_mercury_report@1 + - id: on_mercury_report@1 ref: report_data config: {} # no actions consensus: - - type: + - id: name: trigger_test version: "2" labels: @@ -19,7 +19,7 @@ - triggers.report_data.outputs targets: - - type: write_polygon_mainnet@1 + - id: write_polygon_mainnet@1 config: {} inputs: report: diff --git a/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2_spec.json b/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2_spec.json index f4024e24267..000fa469218 100644 --- a/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2_spec.json +++ b/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_2_spec.json @@ -1,14 +1,14 @@ { "triggers": [ { - "type": "on_mercury_report@1", + "id": "on_mercury_report@1", "ref": "report_data", "config": {} } ], "consensus": [ { - "type": "trigger_test:aaShouldBeFirst_true:chain_ethereum:network_mainnet@2", + "id": "trigger_test:aaShouldBeFirst_true:chain_ethereum:network_mainnet@2", "inputs": { "observations": [ "triggers.report_data.outputs" @@ -19,7 +19,7 @@ ], "targets": [ { - "type": "write_polygon_mainnet@1", + "id": "write_polygon_mainnet@1", "inputs": { "report": [ "consensus.evm_median.outputs.report" @@ -28,4 +28,4 @@ "config": {} } ] -} +} \ No newline at end of file diff --git a/core/services/workflows/testdata/fixtures/workflows/references/failing_1.yaml b/core/services/workflows/testdata/fixtures/workflows/references/failing_1.yaml index 67d6890c47b..b3c984e9892 100644 --- a/core/services/workflows/testdata/fixtures/workflows/references/failing_1.yaml +++ b/core/services/workflows/testdata/fixtures/workflows/references/failing_1.yaml @@ -1,14 +1,14 @@ triggers: -- type: trigger_test@1 +- id: trigger_test@1 config: {} consensus: - - type: offchain_reporting@1 + - id: offchain_reporting@1 ref: offchain_reporting=1 config: {} targets: - - type: write_polygon_mainnet@1 + - id: write_polygon_mainnet@1 ref: write_polygon_mainnet_1 config: {} diff --git a/core/services/workflows/testdata/fixtures/workflows/references/passing_1.yaml b/core/services/workflows/testdata/fixtures/workflows/references/passing_1.yaml index f8c7d20136e..cb2f424e981 100644 --- a/core/services/workflows/testdata/fixtures/workflows/references/passing_1.yaml +++ b/core/services/workflows/testdata/fixtures/workflows/references/passing_1.yaml @@ -1,14 +1,14 @@ triggers: -- type: trigger_test@1 +- id: trigger_test@1 config: {} consensus: - - type: offchain_reporting@1 + - id: offchain_reporting@1 ref: offchain_reporting_1 config: {} targets: - - type: write_polygon_mainnet@1 + - id: write_polygon_mainnet@1 ref: write_polygon_mainnet_1 config: {} diff --git a/core/services/workflows/testdata/fixtures/workflows/versioning/failing_1.yaml b/core/services/workflows/testdata/fixtures/workflows/versioning/failing_1.yaml index b45676388c5..2e41eeb9898 100644 --- a/core/services/workflows/testdata/fixtures/workflows/versioning/failing_1.yaml +++ b/core/services/workflows/testdata/fixtures/workflows/versioning/failing_1.yaml @@ -1,15 +1,15 @@ # Should fail since version is more specific than major triggers: - - type: trigger_test@1.0 + - id: trigger_test@1.0 config: {} consensus: - - type: offchain_reporting@1 + - id: offchain_reporting@1 ref: offchain_reporting_1 config: {} targets: - - type: write_polygon_mainnet@1 + - id: write_polygon_mainnet@1 ref: write_polygon_mainnet_1 config: {} diff --git a/core/services/workflows/testdata/fixtures/workflows/versioning/failing_2.yaml b/core/services/workflows/testdata/fixtures/workflows/versioning/failing_2.yaml index c2a1872b4cf..36cd5b68b6b 100644 --- a/core/services/workflows/testdata/fixtures/workflows/versioning/failing_2.yaml +++ b/core/services/workflows/testdata/fixtures/workflows/versioning/failing_2.yaml @@ -1,16 +1,16 @@ # Should fail since version is more specific than major triggers: - - type: trigger_test@1.0.0 + - id: trigger_test@1.0.0 config: {} consensus: - - type: offchain_reporting@1 + - id: offchain_reporting@1 ref: offchain_reporting_1 config: {} targets: - - type: write_polygon_mainnet@1 + - id: write_polygon_mainnet@1 ref: write_polygon_mainnet_1 config: {} diff --git a/core/services/workflows/testdata/fixtures/workflows/versioning/passing_1.yaml b/core/services/workflows/testdata/fixtures/workflows/versioning/passing_1.yaml index 83bdcc610ef..4579c2899b9 100644 --- a/core/services/workflows/testdata/fixtures/workflows/versioning/passing_1.yaml +++ b/core/services/workflows/testdata/fixtures/workflows/versioning/passing_1.yaml @@ -1,14 +1,14 @@ triggers: - - type: trigger_test@1 + - id: trigger_test@1 config: {} consensus: - - type: offchain_reporting@1-beta.1 + - id: offchain_reporting@1-beta.1 ref: offchain_reporting_1 config: {} targets: - - type: write_polygon_mainnet@1-alpha+sha246er3 + - id: write_polygon_mainnet@1-alpha+sha246er3 ref: write_polygon_mainnet_1 config: {} diff --git a/core/services/workflows/testdata/fixtures/workflows/workflow_schema.json b/core/services/workflows/testdata/fixtures/workflows/workflow_schema.json index 83ecd42ecb9..7f257f7798d 100644 --- a/core/services/workflows/testdata/fixtures/workflows/workflow_schema.json +++ b/core/services/workflows/testdata/fixtures/workflows/workflow_schema.json @@ -6,15 +6,15 @@ "mapping": { "type": "object" }, - "stepDefinitionType": { + "stepDefinitionID": { "oneOf": [ { - "type": "string", + "$id": "string", "pattern": "^[a-z0-9_\\-:]+@(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$" }, { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/smartcontractkit/chainlink/v2/core/services/workflows/step-definition-table-type", + "$id": "https://github.com/smartcontractkit/chainlink/v2/core/services/workflows/step-definition-table-id", "properties": { "name": { "type": "string" @@ -39,12 +39,12 @@ ] } ], - "title": "type" + "title": "id" }, "stepDefinitionYaml": { "properties": { - "type": { - "$ref": "#/$defs/stepDefinitionType" + "id": { + "$ref": "#/$defs/stepDefinitionID" }, "ref": { "type": "string", @@ -60,7 +60,7 @@ "additionalProperties": false, "type": "object", "required": [ - "type", + "id", "config" ] }, @@ -100,4 +100,4 @@ ] } } -} +} \ No newline at end of file diff --git a/core/web/jobs_controller_test.go b/core/web/jobs_controller_test.go index bade8fe293b..0146038d91b 100644 --- a/core/web/jobs_controller_test.go +++ b/core/web/jobs_controller_test.go @@ -397,7 +397,7 @@ func TestJobController_Create_HappyPath(t *testing.T) { owner := "00000000000000000000000000000000000000aa" workflow := ` triggers: - - type: "mercury-trigger" + - id: "mercury-trigger" config: feedIds: - "0x1111111111111111111100000000000000000000000000000000000000000000" @@ -405,7 +405,7 @@ triggers: - "0x3333333333333333333300000000000000000000000000000000000000000000" consensus: - - type: "offchain_reporting" + - id: "offchain_reporting" ref: "evm_median" inputs: observations: @@ -427,14 +427,14 @@ consensus: abi: "mercury_reports bytes[]" targets: - - type: "write_polygon-testnet-mumbai" + - id: "write_polygon-testnet-mumbai" inputs: report: "$(evm_median.outputs.report)" config: address: "0x3F3554832c636721F1fD1822Ccca0354576741Ef" params: ["$(report)"] abi: "receive(report bytes)" - - type: "write_ethereum-testnet-sepolia" + - id: "write_ethereum-testnet-sepolia" inputs: report: "$(evm_median.outputs.report)" config: From 644f5f271d9ed47e999e1d9aa4b99e5de0fd8b89 Mon Sep 17 00:00:00 2001 From: Austin Born Date: Thu, 2 May 2024 05:47:42 -0700 Subject: [PATCH 28/45] Operator Forwarder Production Readiness (#12983) * move oepratorforwarder out of dev/ and add more test cases * Update test locations * Update gas snapshot * Update solc compile * Changeset * Prettier linting + hardhat test updates * Interface naming and test updates * Update Deployer.sol => Deployer.t.sol * Rework OperatorForwarder tests * Update gas snapshot * prettier * Fix Hardhat tests * More style maintenance * Update constant variables in Deployer.t.sol * Update gas snapshot --- .github/workflows/solidity-foundry.yml | 2 +- contracts/.changeset/small-paws-crash.md | 5 + contracts/GNUmakefile | 2 +- .../operatorforwarder.gas-snapshot | 23 +- .../native_solc_compile_all_operatorforwarder | 9 +- .../{dev => }/AuthorizedForwarder.sol | 2 +- .../{dev => }/AuthorizedReceiver.sol | 4 +- .../{dev => }/LinkTokenReceiver.sol | 0 .../operatorforwarder/{dev => }/Operator.sol | 24 +- .../{dev => }/OperatorFactory.sol | 0 .../operatorforwarder/dev/test/operator.t.sol | 100 ------ .../IAuthorizedReceiver.sol} | 2 +- .../IWithdrawal.sol} | 2 +- .../v0.8/operatorforwarder/test/Factory.t.sol | 69 +++++ .../operatorforwarder/test/Forwarder.t.sol | 183 +++++++++++ .../operatorforwarder/test/operator.t.sol | 291 ++++++++++++++++++ .../test/testhelpers/BasicConsumer.sol | 0 .../test/testhelpers/Callback.sol | 21 ++ .../testhelpers/ChainlinkClientHelper.sol | 6 +- .../test/testhelpers/Chainlinked.sol | 2 +- .../{dev => }/test/testhelpers/Consumer.sol | 12 +- .../test/testhelpers/Deployer.t.sol | 33 ++ .../test/testhelpers/EmptyOracle.sol | 4 +- .../test/testhelpers/GasGuzzlingConsumer.sol | 2 +- .../test/testhelpers/GetterSetter.sol | 24 +- .../test/testhelpers/MaliciousChainlink.sol | 4 +- .../test/testhelpers/MaliciousChainlinked.sol | 30 +- .../test/testhelpers/MaliciousConsumer.sol | 6 +- .../MaliciousMultiWordConsumer.sol | 4 +- .../test/testhelpers/MaliciousRequester.sol | 2 +- .../test/testhelpers/MockReceiver.sol | 18 ++ .../test/testhelpers/MultiWordConsumer.sol | 48 ++- contracts/test/v0.8/ChainlinkClient.test.ts | 6 +- .../AuthorizedForwarder.test.ts | 4 +- .../v0.8/operatorforwarder/Operator.test.ts | 34 +- .../operatorforwarder/OperatorFactory.test.ts | 6 +- 36 files changed, 774 insertions(+), 210 deletions(-) create mode 100644 contracts/.changeset/small-paws-crash.md rename contracts/src/v0.8/operatorforwarder/{dev => }/AuthorizedForwarder.sol (97%) rename contracts/src/v0.8/operatorforwarder/{dev => }/AuthorizedReceiver.sol (93%) rename contracts/src/v0.8/operatorforwarder/{dev => }/LinkTokenReceiver.sol (100%) rename contracts/src/v0.8/operatorforwarder/{dev => }/Operator.sol (96%) rename contracts/src/v0.8/operatorforwarder/{dev => }/OperatorFactory.sol (100%) delete mode 100644 contracts/src/v0.8/operatorforwarder/dev/test/operator.t.sol rename contracts/src/v0.8/operatorforwarder/{dev/interfaces/AuthorizedReceiverInterface.sol => interfaces/IAuthorizedReceiver.sol} (87%) rename contracts/src/v0.8/operatorforwarder/{dev/interfaces/WithdrawalInterface.sol => interfaces/IWithdrawal.sol} (93%) create mode 100644 contracts/src/v0.8/operatorforwarder/test/Factory.t.sol create mode 100644 contracts/src/v0.8/operatorforwarder/test/Forwarder.t.sol create mode 100644 contracts/src/v0.8/operatorforwarder/test/operator.t.sol rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/BasicConsumer.sol (100%) create mode 100644 contracts/src/v0.8/operatorforwarder/test/testhelpers/Callback.sol rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/ChainlinkClientHelper.sol (76%) rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/Chainlinked.sol (98%) rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/Consumer.sol (87%) create mode 100644 contracts/src/v0.8/operatorforwarder/test/testhelpers/Deployer.t.sol rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/EmptyOracle.sol (83%) rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/GasGuzzlingConsumer.sol (96%) rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/GetterSetter.sol (71%) rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/MaliciousChainlink.sol (91%) rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/MaliciousChainlinked.sol (80%) rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/MaliciousConsumer.sol (92%) rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/MaliciousMultiWordConsumer.sol (94%) rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/MaliciousRequester.sol (95%) create mode 100644 contracts/src/v0.8/operatorforwarder/test/testhelpers/MockReceiver.sol rename contracts/src/v0.8/operatorforwarder/{dev => }/test/testhelpers/MultiWordConsumer.sol (81%) diff --git a/.github/workflows/solidity-foundry.yml b/.github/workflows/solidity-foundry.yml index 2d62ef864a5..5e2d95ea9d1 100644 --- a/.github/workflows/solidity-foundry.yml +++ b/.github/workflows/solidity-foundry.yml @@ -31,7 +31,7 @@ jobs: strategy: fail-fast: false matrix: - product: [vrf, automation, llo-feeds, l2ep, functions, keystone, shared] + product: [automation, functions, keystone, l2ep, llo-feeds, operatorforwarder, shared, vrf] needs: [changes] name: Foundry Tests ${{ matrix.product }} # See https://github.com/foundry-rs/foundry/issues/3827 diff --git a/contracts/.changeset/small-paws-crash.md b/contracts/.changeset/small-paws-crash.md new file mode 100644 index 00000000000..3a3efa36805 --- /dev/null +++ b/contracts/.changeset/small-paws-crash.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +Update operatorforwarder tests and pull out of dev/ diff --git a/contracts/GNUmakefile b/contracts/GNUmakefile index 4ec8057b975..ba11b396e89 100644 --- a/contracts/GNUmakefile +++ b/contracts/GNUmakefile @@ -1,6 +1,6 @@ # ALL_FOUNDRY_PRODUCTS contains a list of all products that have a foundry # profile defined and use the Foundry snapshots. -ALL_FOUNDRY_PRODUCTS = l2ep llo-feeds functions keystone shared transmission +ALL_FOUNDRY_PRODUCTS = functions keystone l2ep llo-feeds operatorforwarder shared transmission # To make a snapshot for a specific product, either set the `FOUNDRY_PROFILE` env var # or call the target with `FOUNDRY_PROFILE=product` diff --git a/contracts/gas-snapshots/operatorforwarder.gas-snapshot b/contracts/gas-snapshots/operatorforwarder.gas-snapshot index 964c1a91b8d..ee6c063f2f3 100644 --- a/contracts/gas-snapshots/operatorforwarder.gas-snapshot +++ b/contracts/gas-snapshots/operatorforwarder.gas-snapshot @@ -1,2 +1,21 @@ -Operator_cancelRequest:test_Success(uint96) (runs: 256, μ: 306103, ~: 306096) -Operator_cancelRequest:test_afterSuccessfulRequestSucess(uint96) (runs: 256, μ: 384781, ~: 389554) \ No newline at end of file +FactoryTest:test_DeployNewForwarderAndTransferOwnership_Success() (gas: 1059722) +FactoryTest:test_DeployNewForwarder_Success() (gas: 1048209) +FactoryTest:test_DeployNewOperatorAndForwarder_Success() (gas: 4069305) +FactoryTest:test_DeployNewOperator_Success() (gas: 3020464) +ForwarderTest:test_Forward_Success(uint256) (runs: 256, μ: 226200, ~: 227289) +ForwarderTest:test_MultiForward_Success(uint256,uint256) (runs: 256, μ: 257876, ~: 259120) +ForwarderTest:test_OwnerForward_Success() (gas: 30118) +ForwarderTest:test_SetAuthorizedSenders_Success() (gas: 160524) +ForwarderTest:test_TransferOwnershipWithMessage_Success() (gas: 35123) +OperatorTest:test_CancelOracleRequest_Success() (gas: 274436) +OperatorTest:test_CancelOracleRequest_Success() (gas: 274436) +OperatorTest:test_FulfillOracleRequest_Success() (gas: 330603) +OperatorTest:test_FulfillOracleRequest_Success() (gas: 330603) +OperatorTest:test_NotAuthorizedSender_Revert() (gas: 246716) +OperatorTest:test_NotAuthorizedSender_Revert() (gas: 246716) +OperatorTest:test_OracleRequest_Success() (gas: 250019) +OperatorTest:test_OracleRequest_Success() (gas: 250019) +OperatorTest:test_SendRequestAndCancelRequest_Success(uint96) (runs: 256, μ: 387120, ~: 387124) +OperatorTest:test_SendRequestAndCancelRequest_Success(uint96) (runs: 256, μ: 387120, ~: 387124) +OperatorTest:test_SendRequest_Success(uint96) (runs: 256, μ: 303611, ~: 303620) +OperatorTest:test_SendRequest_Success(uint96) (runs: 256, μ: 303611, ~: 303620) \ No newline at end of file diff --git a/contracts/scripts/native_solc_compile_all_operatorforwarder b/contracts/scripts/native_solc_compile_all_operatorforwarder index 2d455994813..c791d50c1d6 100755 --- a/contracts/scripts/native_solc_compile_all_operatorforwarder +++ b/contracts/scripts/native_solc_compile_all_operatorforwarder @@ -28,8 +28,9 @@ compileContract () { } # Contracts -compileContract operatorforwarder/dev/AuthorizedForwarder.sol -compileContract operatorforwarder/dev/AuthorizedReceiver.sol -compileContract operatorforwarder/dev/Operator.sol -compileContract operatorforwarder/dev/OperatorFactory.sol +compileContract operatorforwarder/AuthorizedForwarder.sol +compileContract operatorforwarder/AuthorizedReceiver.sol +compileContract operatorforwarder/LinkTokenReceiver.sol +compileContract operatorforwarder/Operator.sol +compileContract operatorforwarder/OperatorFactory.sol diff --git a/contracts/src/v0.8/operatorforwarder/dev/AuthorizedForwarder.sol b/contracts/src/v0.8/operatorforwarder/AuthorizedForwarder.sol similarity index 97% rename from contracts/src/v0.8/operatorforwarder/dev/AuthorizedForwarder.sol rename to contracts/src/v0.8/operatorforwarder/AuthorizedForwarder.sol index 824ffce6f0f..ffb09248701 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/AuthorizedForwarder.sol +++ b/contracts/src/v0.8/operatorforwarder/AuthorizedForwarder.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.19; -import {ConfirmedOwnerWithProposal} from "../../shared/access/ConfirmedOwnerWithProposal.sol"; +import {ConfirmedOwnerWithProposal} from "../shared/access/ConfirmedOwnerWithProposal.sol"; import {AuthorizedReceiver} from "./AuthorizedReceiver.sol"; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; diff --git a/contracts/src/v0.8/operatorforwarder/dev/AuthorizedReceiver.sol b/contracts/src/v0.8/operatorforwarder/AuthorizedReceiver.sol similarity index 93% rename from contracts/src/v0.8/operatorforwarder/dev/AuthorizedReceiver.sol rename to contracts/src/v0.8/operatorforwarder/AuthorizedReceiver.sol index b741118895f..919602b5acf 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/AuthorizedReceiver.sol +++ b/contracts/src/v0.8/operatorforwarder/AuthorizedReceiver.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.19; -import {AuthorizedReceiverInterface} from "./interfaces/AuthorizedReceiverInterface.sol"; +import {IAuthorizedReceiver} from "./interfaces/IAuthorizedReceiver.sol"; // solhint-disable gas-custom-errors -abstract contract AuthorizedReceiver is AuthorizedReceiverInterface { +abstract contract AuthorizedReceiver is IAuthorizedReceiver { mapping(address sender => bool authorized) private s_authorizedSenders; address[] private s_authorizedSenderList; diff --git a/contracts/src/v0.8/operatorforwarder/dev/LinkTokenReceiver.sol b/contracts/src/v0.8/operatorforwarder/LinkTokenReceiver.sol similarity index 100% rename from contracts/src/v0.8/operatorforwarder/dev/LinkTokenReceiver.sol rename to contracts/src/v0.8/operatorforwarder/LinkTokenReceiver.sol diff --git a/contracts/src/v0.8/operatorforwarder/dev/Operator.sol b/contracts/src/v0.8/operatorforwarder/Operator.sol similarity index 96% rename from contracts/src/v0.8/operatorforwarder/dev/Operator.sol rename to contracts/src/v0.8/operatorforwarder/Operator.sol index e68df5fd075..64882e43cda 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/Operator.sol +++ b/contracts/src/v0.8/operatorforwarder/Operator.sol @@ -3,19 +3,19 @@ pragma solidity 0.8.19; import {AuthorizedReceiver} from "./AuthorizedReceiver.sol"; import {LinkTokenReceiver} from "./LinkTokenReceiver.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; -import {AuthorizedReceiverInterface} from "./interfaces/AuthorizedReceiverInterface.sol"; -import {OperatorInterface} from "../../interfaces/OperatorInterface.sol"; -import {IOwnable} from "../../shared/interfaces/IOwnable.sol"; -import {WithdrawalInterface} from "./interfaces/WithdrawalInterface.sol"; -import {OracleInterface} from "../../interfaces/OracleInterface.sol"; -import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; +import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol"; +import {LinkTokenInterface} from "../shared/interfaces/LinkTokenInterface.sol"; +import {IAuthorizedReceiver} from "./interfaces/IAuthorizedReceiver.sol"; +import {OperatorInterface} from "../interfaces/OperatorInterface.sol"; +import {IOwnable} from "../shared/interfaces/IOwnable.sol"; +import {IWithdrawal} from "./interfaces/IWithdrawal.sol"; +import {OracleInterface} from "../interfaces/OracleInterface.sol"; +import {SafeCast} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; // @title The Chainlink Operator contract // @notice Node operators can deploy this contract to fulfill requests sent to them // solhint-disable gas-custom-errors -contract Operator is AuthorizedReceiver, ConfirmedOwner, LinkTokenReceiver, OperatorInterface, WithdrawalInterface { +contract Operator is AuthorizedReceiver, ConfirmedOwner, LinkTokenReceiver, OperatorInterface, IWithdrawal { struct Commitment { bytes31 paramsHash; uint8 dataVersion; @@ -241,7 +241,7 @@ contract Operator is AuthorizedReceiver, ConfirmedOwner, LinkTokenReceiver, Oper emit TargetsUpdatedAuthorizedSenders(targets, senders, msg.sender); for (uint256 i = 0; i < targets.length; ++i) { - AuthorizedReceiverInterface(targets[i]).setAuthorizedSenders(senders); + IAuthorizedReceiver(targets[i]).setAuthorizedSenders(senders); } } @@ -266,14 +266,14 @@ contract Operator is AuthorizedReceiver, ConfirmedOwner, LinkTokenReceiver, Oper function withdraw( address recipient, uint256 amount - ) external override(OracleInterface, WithdrawalInterface) onlyOwner validateAvailableFunds(amount) { + ) external override(OracleInterface, IWithdrawal) onlyOwner validateAvailableFunds(amount) { assert(i_linkToken.transfer(recipient, amount)); } // @notice Displays the amount of LINK that is available for the node operator to withdraw // @dev We use `ONE_FOR_CONSISTENT_GAS_COST` in place of 0 in storage // @return The amount of withdrawable LINK on the contract - function withdrawable() external view override(OracleInterface, WithdrawalInterface) returns (uint256) { + function withdrawable() external view override(OracleInterface, IWithdrawal) returns (uint256) { return _fundsAvailable(); } diff --git a/contracts/src/v0.8/operatorforwarder/dev/OperatorFactory.sol b/contracts/src/v0.8/operatorforwarder/OperatorFactory.sol similarity index 100% rename from contracts/src/v0.8/operatorforwarder/dev/OperatorFactory.sol rename to contracts/src/v0.8/operatorforwarder/OperatorFactory.sol diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/operator.t.sol b/contracts/src/v0.8/operatorforwarder/dev/test/operator.t.sol deleted file mode 100644 index 96975a2baf4..00000000000 --- a/contracts/src/v0.8/operatorforwarder/dev/test/operator.t.sol +++ /dev/null @@ -1,100 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {Test} from "forge-std/Test.sol"; -import {Operator} from "../Operator.sol"; -import {ChainlinkClientHelper} from "./testhelpers/ChainlinkClientHelper.sol"; -import {LinkToken} from "../../../shared/token/ERC677/LinkToken.sol"; - -contract Operator_cancelRequest is Test { - address public s_link; - ChainlinkClientHelper public s_client; - Operator public s_operator; - - function setUp() public { - s_link = address(new LinkToken()); - s_client = new ChainlinkClientHelper(s_link); - - address[] memory auth = new address[](1); - auth[0] = address(this); - s_operator = new Operator(s_link, address(this)); - s_operator.setAuthorizedSenders(auth); - } - - function test_Success(uint96 payment) public { - payment = uint96(bound(payment, 1, type(uint96).max)); - deal(s_link, address(s_client), payment); - // We're going to cancel one request and fulfil the other - bytes32 requestIdToCancel = s_client.sendRequest(address(s_operator), payment); - - // Nothing withdrawable - // 1 payment in escrow - // Client has zero link - assertEq(s_operator.withdrawable(), 0); - assertEq(LinkToken(s_link).balanceOf(address(s_operator)), payment); - assertEq(LinkToken(s_link).balanceOf(address(s_client)), 0); - - // Advance time so we can cancel - uint256 expiration = block.timestamp + s_operator.EXPIRYTIME(); - vm.warp(expiration + 1); - s_client.cancelRequest(requestIdToCancel, payment, expiration); - - // 1 payment has been returned due to the cancellation. - assertEq(s_operator.withdrawable(), 0); - assertEq(LinkToken(s_link).balanceOf(address(s_operator)), 0); - assertEq(LinkToken(s_link).balanceOf(address(s_client)), payment); - } - - function test_afterSuccessfulRequestSucess(uint96 payment) public { - payment = uint96(bound(payment, 1, type(uint96).max) / 2); - deal(s_link, address(s_client), 2 * payment); - - // Initial state, client has 2 payments, zero in escrow, zero in the operator, zeero withdrawable - assertEq(s_operator.withdrawable(), 0); - assertEq(LinkToken(s_link).balanceOf(address(s_operator)), 0); - assertEq(LinkToken(s_link).balanceOf(address(s_client)), 2 * payment); - - // We're going to cancel one request and fulfil the other - bytes32 requestId = s_client.sendRequest(address(s_operator), payment); - bytes32 requestIdToCancel = s_client.sendRequest(address(s_operator), payment); - - // Nothing withdrawable - // Operator now has the 2 payments in escrow - // Client has zero payments - assertEq(s_operator.withdrawable(), 0); - assertEq(LinkToken(s_link).balanceOf(address(s_operator)), 2 * payment); - assertEq(LinkToken(s_link).balanceOf(address(s_client)), 0); - - // Fulfill one request - uint256 expiration = block.timestamp + s_operator.EXPIRYTIME(); - s_operator.fulfillOracleRequest( - requestId, - payment, - address(s_client), - s_client.FULFILSELECTOR(), - expiration, - bytes32(hex"01") - ); - // 1 payment withdrawable from fulfilling `requestId`, 1 payment in escrow - assertEq(s_operator.withdrawable(), payment); - assertEq(LinkToken(s_link).balanceOf(address(s_operator)), 2 * payment); - assertEq(LinkToken(s_link).balanceOf(address(s_client)), 0); - - // Advance time so we can cancel - vm.warp(expiration + 1); - s_client.cancelRequest(requestIdToCancel, payment, expiration); - - // 1 payment has been returned due to the cancellation, 1 payment should be withdrawable - assertEq(s_operator.withdrawable(), payment); - assertEq(LinkToken(s_link).balanceOf(address(s_operator)), payment); - assertEq(LinkToken(s_link).balanceOf(address(s_client)), payment); - - // Withdraw the remaining payment - s_operator.withdraw(address(s_client), payment); - - // End state is exactly the same as the initial state. - assertEq(s_operator.withdrawable(), 0); - assertEq(LinkToken(s_link).balanceOf(address(s_operator)), 0); - assertEq(LinkToken(s_link).balanceOf(address(s_client)), 2 * payment); - } -} diff --git a/contracts/src/v0.8/operatorforwarder/dev/interfaces/AuthorizedReceiverInterface.sol b/contracts/src/v0.8/operatorforwarder/interfaces/IAuthorizedReceiver.sol similarity index 87% rename from contracts/src/v0.8/operatorforwarder/dev/interfaces/AuthorizedReceiverInterface.sol rename to contracts/src/v0.8/operatorforwarder/interfaces/IAuthorizedReceiver.sol index 28b20b14f33..78140d58682 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/interfaces/AuthorizedReceiverInterface.sol +++ b/contracts/src/v0.8/operatorforwarder/interfaces/IAuthorizedReceiver.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -interface AuthorizedReceiverInterface { +interface IAuthorizedReceiver { function isAuthorizedSender(address sender) external view returns (bool); function getAuthorizedSenders() external returns (address[] memory); diff --git a/contracts/src/v0.8/operatorforwarder/dev/interfaces/WithdrawalInterface.sol b/contracts/src/v0.8/operatorforwarder/interfaces/IWithdrawal.sol similarity index 93% rename from contracts/src/v0.8/operatorforwarder/dev/interfaces/WithdrawalInterface.sol rename to contracts/src/v0.8/operatorforwarder/interfaces/IWithdrawal.sol index c064b0627b5..433738d406f 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/interfaces/WithdrawalInterface.sol +++ b/contracts/src/v0.8/operatorforwarder/interfaces/IWithdrawal.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -interface WithdrawalInterface { +interface IWithdrawal { // @notice transfer LINK held by the contract belonging to msg.sender to // another address // @param recipient is the address to send the LINK to diff --git a/contracts/src/v0.8/operatorforwarder/test/Factory.t.sol b/contracts/src/v0.8/operatorforwarder/test/Factory.t.sol new file mode 100644 index 00000000000..d54dc620460 --- /dev/null +++ b/contracts/src/v0.8/operatorforwarder/test/Factory.t.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import {Deployer} from "./testhelpers/Deployer.t.sol"; +import {AuthorizedForwarder} from "../AuthorizedForwarder.sol"; +import {Operator} from "../Operator.sol"; + +contract FactoryTest is Deployer { + function setUp() public { + _setUp(); + + vm.startPrank(ALICE); + } + + function test_DeployNewOperator_Success() public { + // Deploy a new operator using the factory. + address newOperator = s_factory.deployNewOperator(); + // Assert that the new operator was indeed created by the factory. + assertTrue(s_factory.created(newOperator)); + // Ensure that Alice is the owner of the newly deployed operator. + require(Operator(newOperator).owner() == ALICE); + } + + function test_DeployNewOperatorAndForwarder_Success() public { + // Deploy both a new operator and a new forwarder using the factory. + (address newOperator, address newForwarder) = s_factory.deployNewOperatorAndForwarder(); + + // Assert that the new operator and the new forwarder were indeed created by the factory. + assertTrue(s_factory.created(newOperator)); + assertTrue(s_factory.created(newForwarder)); + // Ensure that Alice is the owner of the newly deployed operator. + require(Operator(newOperator).owner() == ALICE); + + //Operator to accept ownership + vm.startPrank(newOperator); + AuthorizedForwarder(newForwarder).acceptOwnership(); + + // Ensure that the newly deployed operator is the owner of the newly deployed forwarder. + require(AuthorizedForwarder(newForwarder).owner() == newOperator, "operator is not the owner"); + } + + function test_DeployNewForwarder_Success() public { + // Deploy a new forwarder using the factory. + address newForwarder = s_factory.deployNewForwarder(); + // Assert that the new forwarder was indeed created by the factory. + assertTrue(s_factory.created(newForwarder)); + // Ensure that Alice is the owner of the newly deployed forwarder. + require(AuthorizedForwarder(newForwarder).owner() == ALICE); + } + + function test_DeployNewForwarderAndTransferOwnership_Success() public { + // Deploy a new forwarder with a proposal to transfer its ownership to Bob. + address newForwarder = s_factory.deployNewForwarderAndTransferOwnership(BOB, new bytes(0)); + // Assert that the new forwarder was indeed created by the factory. + assertTrue(s_factory.created(newForwarder)); + // Ensure that Alice is still the current owner of the newly deployed forwarder. + require(AuthorizedForwarder(newForwarder).owner() == ALICE); + + // Only proposed owner can call acceptOwnership() + vm.expectRevert("Must be proposed owner"); + AuthorizedForwarder(newForwarder).acceptOwnership(); + + vm.startPrank(BOB); + // Let Bob accept the ownership. + AuthorizedForwarder(newForwarder).acceptOwnership(); + // Ensure that Bob is now the owner of the forwarder after the transfer. + require(AuthorizedForwarder(newForwarder).owner() == BOB); + } +} diff --git a/contracts/src/v0.8/operatorforwarder/test/Forwarder.t.sol b/contracts/src/v0.8/operatorforwarder/test/Forwarder.t.sol new file mode 100644 index 00000000000..ba6ce1c17c1 --- /dev/null +++ b/contracts/src/v0.8/operatorforwarder/test/Forwarder.t.sol @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import {Deployer} from "./testhelpers/Deployer.t.sol"; +import {AuthorizedForwarder} from "../AuthorizedForwarder.sol"; + +contract ForwarderTest is Deployer { + AuthorizedForwarder internal s_forwarder; + + function setUp() public { + _setUp(); + + vm.prank(ALICE); + s_forwarder = AuthorizedForwarder(s_factory.deployNewForwarder()); + } + + function test_SetAuthorizedSenders_Success() public { + address[] memory senders; + + // Expect a revert when trying to set an empty list of authorized senders + vm.expectRevert("Cannot set authorized senders"); + s_forwarder.setAuthorizedSenders(senders); + + vm.prank(ALICE); + // Expect a revert because the sender list is empty + vm.expectRevert("Must have at least 1 sender"); + s_forwarder.setAuthorizedSenders(senders); + + // Create a list with two identical sender addresses + senders = new address[](2); + senders[0] = SENDER_1; + senders[1] = SENDER_1; + + vm.prank(ALICE); + // Expect a revert because the sender list has duplicates + vm.expectRevert("Must not have duplicate senders"); + s_forwarder.setAuthorizedSenders(senders); + + // Set the second sender to a different address + senders[1] = SENDER_2; + + vm.prank(ALICE); + // Update the authorized senders list + s_forwarder.setAuthorizedSenders(senders); + + // Check if both SENDER_1 and SENDER_2 are now authorized + assertTrue(s_forwarder.isAuthorizedSender(SENDER_1)); + assertTrue(s_forwarder.isAuthorizedSender(SENDER_2)); + + // Fetch the authorized senders and verify they match the set addresses + address[] memory returnedSenders = s_forwarder.getAuthorizedSenders(); + require(returnedSenders[0] == senders[0]); + require(returnedSenders[1] == senders[1]); + + // Create a new list with only SENDER_3 + senders = new address[](1); + senders[0] = SENDER_3; + + // Prank 'alice' and update the authorized senders to just SENDER_3 + vm.prank(ALICE); + s_forwarder.setAuthorizedSenders(senders); + + // Ensure SENDER_1 and SENDER_2 are no longer authorized + assertFalse(s_forwarder.isAuthorizedSender(SENDER_1)); + assertFalse(s_forwarder.isAuthorizedSender(SENDER_2)); + + // Check that SENDER_3 is now the only authorized sender + assertTrue(s_forwarder.isAuthorizedSender(SENDER_3)); + returnedSenders = s_forwarder.getAuthorizedSenders(); + require(returnedSenders[0] == senders[0]); + } + + function test_Forward_Success(uint256 _value) public { + _addSenders(); + + vm.expectRevert("Not authorized sender"); + s_forwarder.forward(address(0), new bytes(0)); + + vm.prank(SENDER_1); + vm.expectRevert("Cannot forward to Link token"); + s_forwarder.forward(address(s_link), new bytes(0)); + + vm.prank(SENDER_1); + vm.expectRevert("Must forward to a contract"); + s_forwarder.forward(address(0), new bytes(0)); + + vm.prank(SENDER_1); + vm.expectRevert("Forwarded call reverted without reason"); + s_forwarder.forward(address(s_mockReceiver), new bytes(0)); + + vm.prank(SENDER_1); + vm.expectRevert("test revert message"); + s_forwarder.forward(address(s_mockReceiver), abi.encodeWithSignature("revertMessage()")); + + vm.prank(SENDER_1); + s_forwarder.forward(address(s_mockReceiver), abi.encodeWithSignature("receiveData(uint256)", _value)); + + require(s_mockReceiver.getValue() == _value); + } + + function test_MultiForward_Success(uint256 _value1, uint256 _value2) public { + _addSenders(); + + address[] memory tos; + bytes[] memory datas; + + vm.expectRevert("Not authorized sender"); + s_forwarder.multiForward(tos, datas); + + tos = new address[](2); + datas = new bytes[](1); + + vm.prank(SENDER_1); + vm.expectRevert("Arrays must have the same length"); + s_forwarder.multiForward(tos, datas); + + datas = new bytes[](2); + + vm.prank(SENDER_1); + vm.expectRevert("Must forward to a contract"); + s_forwarder.multiForward(tos, datas); + + tos[0] = address(s_mockReceiver); + tos[1] = address(s_link); + + vm.prank(SENDER_1); + vm.expectRevert("Forwarded call reverted without reason"); + s_forwarder.multiForward(tos, datas); + + datas[0] = abi.encodeWithSignature("receiveData(uint256)", _value1); + datas[1] = abi.encodeWithSignature("receiveData(uint256)", _value2); + + vm.prank(SENDER_1); + vm.expectRevert("Cannot forward to Link token"); + s_forwarder.multiForward(tos, datas); + + tos[1] = address(s_mockReceiver); + + vm.prank(SENDER_1); + s_forwarder.multiForward(tos, datas); + + require(s_mockReceiver.getValue() == _value2); + } + + function test_OwnerForward_Success() public { + vm.expectRevert("Only callable by owner"); + s_forwarder.ownerForward(address(0), new bytes(0)); + + vm.prank(ALICE); + vm.expectRevert("Forwarded call reverted without reason"); + s_forwarder.ownerForward(address(s_link), new bytes(0)); + + vm.prank(ALICE); + s_forwarder.ownerForward(address(s_link), abi.encodeWithSignature("balanceOf(address)", address(0))); + } + + function test_TransferOwnershipWithMessage_Success() public { + vm.prank(BOB); + vm.expectRevert("Only callable by owner"); + s_forwarder.transferOwnershipWithMessage(BOB, new bytes(0)); + + vm.prank(ALICE); + s_forwarder.transferOwnershipWithMessage(BOB, new bytes(0)); + + vm.expectRevert("Must be proposed owner"); + s_forwarder.acceptOwnership(); + + vm.prank(BOB); + s_forwarder.acceptOwnership(); + + require(s_forwarder.owner() == BOB); + } + + function _addSenders() internal { + address[] memory senders = new address[](3); + senders[0] = SENDER_1; + senders[1] = SENDER_2; + senders[2] = SENDER_3; + + vm.prank(ALICE); + s_forwarder.setAuthorizedSenders(senders); + } +} diff --git a/contracts/src/v0.8/operatorforwarder/test/operator.t.sol b/contracts/src/v0.8/operatorforwarder/test/operator.t.sol new file mode 100644 index 00000000000..6c4a7c2ae1a --- /dev/null +++ b/contracts/src/v0.8/operatorforwarder/test/operator.t.sol @@ -0,0 +1,291 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {Operator} from "../Operator.sol"; +import {Callback} from "./testhelpers/Callback.sol"; +import {ChainlinkClientHelper} from "./testhelpers/ChainlinkClientHelper.sol"; +import {Deployer} from "./testhelpers/Deployer.t.sol"; + +contract OperatorTest is Deployer { + ChainlinkClientHelper private s_client; + Callback private s_callback; + Operator private s_operator; + + function setUp() public { + _setUp(); + s_client = new ChainlinkClientHelper(address(s_link)); + + address[] memory auth = new address[](1); + auth[0] = address(this); + s_operator = new Operator(address(s_link), address(this)); + s_operator.setAuthorizedSenders(auth); + + s_callback = new Callback(address(s_operator)); + } + + function test_SendRequest_Success(uint96 payment) public { + vm.assume(payment > 0); + deal(address(s_link), address(s_client), payment); + // We're going to cancel one request and fulfill the other + bytes32 requestIdToCancel = s_client.sendRequest(address(s_operator), payment); + + // Nothing withdrawable + // 1 payment in escrow + // Client has zero link + assertEq(s_operator.withdrawable(), 0); + assertEq(s_link.balanceOf(address(s_operator)), payment); + assertEq(s_link.balanceOf(address(s_client)), 0); + + // Advance time so we can cancel + uint256 expiration = block.timestamp + s_operator.EXPIRYTIME(); + vm.warp(expiration + 1); + s_client.cancelRequest(requestIdToCancel, payment, expiration); + + // 1 payment has been returned due to the cancellation. + assertEq(s_operator.withdrawable(), 0); + assertEq(s_link.balanceOf(address(s_operator)), 0); + assertEq(s_link.balanceOf(address(s_client)), payment); + } + + function test_SendRequestAndCancelRequest_Success(uint96 payment) public { + vm.assume(payment > 1); + payment /= payment; + + deal(address(s_link), address(s_client), 2 * payment); + + // Initial state, client has 2 payments, zero in escrow, zero in the operator, zeero withdrawable + assertEq(s_operator.withdrawable(), 0); + assertEq(s_link.balanceOf(address(s_operator)), 0); + assertEq(s_link.balanceOf(address(s_client)), 2 * payment); + + // We're going to cancel one request and fulfill the other + bytes32 requestId = s_client.sendRequest(address(s_operator), payment); + bytes32 requestIdToCancel = s_client.sendRequest(address(s_operator), payment); + + // Nothing withdrawable + // Operator now has the 2 payments in escrow + // Client has zero payments + assertEq(s_operator.withdrawable(), 0); + assertEq(s_link.balanceOf(address(s_operator)), 2 * payment); + assertEq(s_link.balanceOf(address(s_client)), 0); + + // Fulfill one request + uint256 expiration = block.timestamp + s_operator.EXPIRYTIME(); + s_operator.fulfillOracleRequest( + requestId, + payment, + address(s_client), + s_client.FULFILL_SELECTOR(), + expiration, + bytes32(hex"01") + ); + // 1 payment withdrawable from fulfilling `requestId`, 1 payment in escrow + assertEq(s_operator.withdrawable(), payment); + assertEq(s_link.balanceOf(address(s_operator)), 2 * payment); + assertEq(s_link.balanceOf(address(s_client)), 0); + + // Advance time so we can cancel + vm.warp(expiration + 1); + s_client.cancelRequest(requestIdToCancel, payment, expiration); + + // 1 payment has been returned due to the cancellation, 1 payment should be withdrawable + assertEq(s_operator.withdrawable(), payment); + assertEq(s_link.balanceOf(address(s_operator)), payment); + assertEq(s_link.balanceOf(address(s_client)), payment); + + // Withdraw the remaining payment + s_operator.withdraw(address(s_client), payment); + + // End state is exactly the same as the initial state. + assertEq(s_operator.withdrawable(), 0); + assertEq(s_link.balanceOf(address(s_operator)), 0); + assertEq(s_link.balanceOf(address(s_client)), 2 * payment); + } + + function test_OracleRequest_Success() public { + // Define some mock values + bytes32 specId = keccak256("testSpec"); + bytes4 callbackFunctionId = bytes4(keccak256("callback(bytes32)")); + uint256 nonce = 0; + uint256 dataVersion = 1; + bytes memory data = ""; + + uint256 initialLinkBalance = s_link.balanceOf(address(s_operator)); + uint256 payment = 1 ether; // Mock payment value + + uint256 withdrawableBefore = s_operator.withdrawable(); + + // Send LINK tokens to the Operator contract using `transferAndCall` + deal(address(s_link), ALICE, payment); + assertEq(s_link.balanceOf(ALICE), 1 ether, "balance update failed"); + + vm.prank(ALICE); + s_link.transferAndCall( + address(s_operator), + payment, + abi.encodeWithSignature( + "oracleRequest(address,uint256,bytes32,address,bytes4,uint256,uint256,bytes)", + address(this), + payment, + specId, + address(s_callback), + callbackFunctionId, + nonce, + dataVersion, + data + ) + ); + + // Check that the LINK tokens were transferred to the Operator contract + assertEq(s_link.balanceOf(address(s_operator)), initialLinkBalance + payment); + // No withdrawable LINK as it's all locked + assertEq(s_operator.withdrawable(), withdrawableBefore); + } + + function test_FulfillOracleRequest_Success() public { + // This test file is the callback target and actual sender contract + // so we should enable it to set Authorised senders to itself + address[] memory senders = new address[](2); + senders[0] = address(this); + senders[0] = BOB; + + s_operator.setAuthorizedSenders(senders); + + uint256 withdrawableBefore = s_operator.withdrawable(); + + // Define mock values for creating a new oracle request + bytes32 specId = keccak256("testSpecForFulfill"); + bytes4 callbackFunctionId = bytes4(keccak256("callback(bytes32)")); + uint256 nonce = 1; + uint256 dataVersion = 1; + bytes memory dataBytes = ""; + uint256 payment = 1 ether; + uint256 expiration = block.timestamp + 5 minutes; + + // Convert bytes to bytes32 + bytes32 data = bytes32(keccak256(dataBytes)); + + // Send LINK tokens to the Operator contract using `transferAndCall` + deal(address(s_link), BOB, payment); + vm.prank(BOB); + s_link.transferAndCall( + address(s_operator), + payment, + abi.encodeWithSignature( + "oracleRequest(address,uint256,bytes32,address,bytes4,uint256,uint256,bytes)", + address(this), + payment, + specId, + address(s_callback), + callbackFunctionId, + nonce, + dataVersion, + dataBytes + ) + ); + + // Fulfill the request using the operator + bytes32 requestId = keccak256(abi.encodePacked(BOB, nonce)); + vm.prank(BOB); + s_operator.fulfillOracleRequest(requestId, payment, address(s_callback), callbackFunctionId, expiration, data); + + assertEq(s_callback.getCallbacksReceived(), 1, "Oracle request was not fulfilled"); + + // Withdrawable balance + assertEq(s_operator.withdrawable(), withdrawableBefore + payment, "Internal accounting not updated correctly"); + } + + function test_CancelOracleRequest_Success() public { + // Define mock values for creating a new oracle request + bytes32 specId = keccak256("testSpecForCancel"); + bytes4 callbackFunctionId = bytes4(keccak256("callback(bytes32)")); + uint256 nonce = 2; + uint256 dataVersion = 1; + bytes memory dataBytes = ""; + uint256 payment = 1 ether; + uint256 expiration = block.timestamp + 5 minutes; + + uint256 withdrawableBefore = s_operator.withdrawable(); + + // Send LINK tokens to the Operator contract using `transferAndCall` + deal(address(s_link), BOB, payment); + vm.prank(BOB); + s_link.transferAndCall( + address(s_operator), + payment, + abi.encodeWithSignature( + "oracleRequest(address,uint256,bytes32,address,bytes4,uint256,uint256,bytes)", + BOB, + payment, + specId, + BOB, + callbackFunctionId, + nonce, + dataVersion, + dataBytes + ) + ); + + // No withdrawable balance as it's all locked + assertEq(s_operator.withdrawable(), withdrawableBefore, "Internal accounting not updated correctly"); + + bytes32 requestId = keccak256(abi.encodePacked(BOB, nonce)); + + vm.startPrank(ALICE); + vm.expectRevert(bytes("Params do not match request ID")); + s_operator.cancelOracleRequest(requestId, payment, callbackFunctionId, expiration); + + vm.startPrank(BOB); + vm.expectRevert(bytes("Request is not expired")); + s_operator.cancelOracleRequest(requestId, payment, callbackFunctionId, expiration); + + vm.warp(expiration); + s_operator.cancelOracleRequest(requestId, payment, callbackFunctionId, expiration); + + // Check if the LINK tokens were refunded to the sender (bob in this case) + assertEq(s_link.balanceOf(BOB), 1 ether, "Oracle request was not canceled properly"); + + assertEq(s_operator.withdrawable(), withdrawableBefore, "Internal accounting not updated correctly"); + } + + function test_NotAuthorizedSender_Revert() public { + bytes32 specId = keccak256("unauthorizedFulfillSpec"); + bytes4 callbackFunctionId = bytes4(keccak256("callback(bytes32)")); + uint256 nonce = 5; + uint256 dataVersion = 1; + bytes memory dataBytes = ""; + uint256 payment = 1 ether; + uint256 expiration = block.timestamp + 5 minutes; + + deal(address(s_link), ALICE, payment); + vm.prank(ALICE); + s_link.transferAndCall( + address(s_operator), + payment, + abi.encodeWithSignature( + "oracleRequest(address,uint256,bytes32,address,bytes4,uint256,uint256,bytes)", + ALICE, + payment, + specId, + address(s_callback), + callbackFunctionId, + nonce, + dataVersion, + dataBytes + ) + ); + + bytes32 requestId = keccak256(abi.encodePacked(ALICE, nonce)); + + vm.prank(BOB); + vm.expectRevert(bytes("Not authorized sender")); + s_operator.fulfillOracleRequest( + requestId, + payment, + address(s_callback), + callbackFunctionId, + expiration, + bytes32(keccak256(dataBytes)) + ); + } +} diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/BasicConsumer.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/BasicConsumer.sol similarity index 100% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/BasicConsumer.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/BasicConsumer.sol diff --git a/contracts/src/v0.8/operatorforwarder/test/testhelpers/Callback.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/Callback.sol new file mode 100644 index 00000000000..9dccfed428a --- /dev/null +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/Callback.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +contract Callback { + address private s_operator; + uint256 private s_callbacksReceived = 0; + + constructor(address _operator) { + s_operator = _operator; + } + + // Callback function for oracle request fulfillment + function callback(bytes32) public { + require(msg.sender == s_operator, "Only Operator can call this function"); + s_callbacksReceived += 1; + } + + function getCallbacksReceived() public view returns (uint256) { + return s_callbacksReceived; + } +} diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/ChainlinkClientHelper.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/ChainlinkClientHelper.sol similarity index 76% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/ChainlinkClientHelper.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/ChainlinkClientHelper.sol index d15eb07c8c9..9b6ba6bb432 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/ChainlinkClientHelper.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/ChainlinkClientHelper.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {ChainlinkClient} from "../../../../ChainlinkClient.sol"; +import {ChainlinkClient} from "../../../ChainlinkClient.sol"; contract ChainlinkClientHelper is ChainlinkClient { - bytes4 public constant FULFILSELECTOR = this.fulfill.selector; + bytes4 public constant FULFILL_SELECTOR = this.fulfill.selector; constructor(address link) { _setChainlinkToken(link); } function sendRequest(address op, uint256 payment) external returns (bytes32) { - return _sendChainlinkRequestTo(op, _buildOperatorRequest(bytes32(hex"10"), FULFILSELECTOR), payment); + return _sendChainlinkRequestTo(op, _buildOperatorRequest(bytes32(hex"10"), FULFILL_SELECTOR), payment); } function cancelRequest(bytes32 requestId, uint256 payment, uint256 expiration) external { diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/Chainlinked.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/Chainlinked.sol similarity index 98% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/Chainlinked.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/Chainlinked.sol index 86dc474e8a6..dba5d407623 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/Chainlinked.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/Chainlinked.sol @@ -1,6 +1,6 @@ pragma solidity ^0.8.0; -import {ChainlinkClient, Chainlink} from "../../../../ChainlinkClient.sol"; +import {ChainlinkClient, Chainlink} from "../../../ChainlinkClient.sol"; /** * @title The Chainlinked contract diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/Consumer.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/Consumer.sol similarity index 87% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/Consumer.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/Consumer.sol index 0d01778e19e..82709d3def8 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/Consumer.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/Consumer.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {ChainlinkClient, ChainlinkRequestInterface, LinkTokenInterface} from "../../../../ChainlinkClient.sol"; -import {Chainlink} from "../../../../Chainlink.sol"; +import {ChainlinkClient, ChainlinkRequestInterface, LinkTokenInterface} from "../../../ChainlinkClient.sol"; +import {Chainlink} from "../../../Chainlink.sol"; contract Consumer is ChainlinkClient { using Chainlink for Chainlink.Request; bytes32 internal s_specId; - bytes32 public currentPrice; + bytes32 internal s_currentPrice; event RequestFulfilled( bytes32 indexed requestId, // User-defined ID @@ -50,6 +50,10 @@ contract Consumer is ChainlinkClient { function fulfill(bytes32 _requestId, bytes32 _price) public recordChainlinkFulfillment(_requestId) { emit RequestFulfilled(_requestId, _price); - currentPrice = _price; + s_currentPrice = _price; + } + + function getCurrentPrice() public view returns (bytes32) { + return s_currentPrice; } } diff --git a/contracts/src/v0.8/operatorforwarder/test/testhelpers/Deployer.t.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/Deployer.t.sol new file mode 100644 index 00000000000..da746c7ff8c --- /dev/null +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/Deployer.t.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import {Test} from "forge-std/Test.sol"; + +import {MockReceiver} from "./MockReceiver.sol"; +import {AuthorizedForwarder} from "../../AuthorizedForwarder.sol"; +import {Operator} from "../../Operator.sol"; +import {OperatorFactory} from "../../OperatorFactory.sol"; +import {LinkToken} from "../../../shared/token/ERC677/LinkToken.sol"; + +abstract contract Deployer is Test { + OperatorFactory internal s_factory; + LinkToken internal s_link; + MockReceiver internal s_mockReceiver; + + address internal constant ALICE = address(0x101); + address internal constant BOB = address(0x102); + address internal constant SENDER_1 = address(0x103); + address internal constant SENDER_2 = address(0x104); + address internal constant SENDER_3 = address(0x105); + + function _setUp() internal { + _deploy(); + } + + function _deploy() internal { + s_link = new LinkToken(); + s_factory = new OperatorFactory(address(s_link)); + + s_mockReceiver = new MockReceiver(); + } +} diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/EmptyOracle.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/EmptyOracle.sol similarity index 83% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/EmptyOracle.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/EmptyOracle.sol index 2abe393151e..f278791d2bb 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/EmptyOracle.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/EmptyOracle.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {ChainlinkRequestInterface} from "../../../../interfaces/ChainlinkRequestInterface.sol"; -import {OracleInterface} from "../../../../interfaces/OracleInterface.sol"; +import {ChainlinkRequestInterface} from "../../../interfaces/ChainlinkRequestInterface.sol"; +import {OracleInterface} from "../../../interfaces/OracleInterface.sol"; /* solhint-disable no-empty-blocks */ contract EmptyOracle is ChainlinkRequestInterface, OracleInterface { diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/GasGuzzlingConsumer.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/GasGuzzlingConsumer.sol similarity index 96% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/GasGuzzlingConsumer.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/GasGuzzlingConsumer.sol index 54ff0e30e66..029102018b0 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/GasGuzzlingConsumer.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/GasGuzzlingConsumer.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; import {Consumer} from "./Consumer.sol"; -import {Chainlink} from "../../../../Chainlink.sol"; +import {Chainlink} from "../../../Chainlink.sol"; contract GasGuzzlingConsumer is Consumer { using Chainlink for Chainlink.Request; diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/GetterSetter.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/GetterSetter.sol similarity index 71% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/GetterSetter.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/GetterSetter.sol index 494da582e1b..722362bc4aa 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/GetterSetter.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/GetterSetter.sol @@ -3,10 +3,10 @@ pragma solidity ^0.8.0; // GetterSetter is a contract to aid debugging and testing during development. // solhint-disable contract GetterSetter { - bytes32 public getBytes32; - uint256 public getUint256; - bytes32 public requestId; - bytes public getBytes; + bytes32 private s_getBytes32; + uint256 private s_getUint256; + bytes32 private s_requestId; + bytes private s_getBytes; event SetBytes32(address indexed from, bytes32 indexed value); event SetUint256(address indexed from, uint256 indexed value); @@ -15,32 +15,36 @@ contract GetterSetter { event Output(bytes32 b32, uint256 u256, bytes32 b322); function setBytes32(bytes32 _value) public { - getBytes32 = _value; + s_getBytes32 = _value; emit SetBytes32(msg.sender, _value); } function requestedBytes32(bytes32 _requestId, bytes32 _value) public { - requestId = _requestId; + s_requestId = _requestId; setBytes32(_value); } function setBytes(bytes memory _value) public { - getBytes = _value; + s_getBytes = _value; emit SetBytes(msg.sender, _value); } + function getBytes() public view returns (bytes memory _value) { + return s_getBytes; + } + function requestedBytes(bytes32 _requestId, bytes memory _value) public { - requestId = _requestId; + s_requestId = _requestId; setBytes(_value); } function setUint256(uint256 _value) public { - getUint256 = _value; + s_getUint256 = _value; emit SetUint256(msg.sender, _value); } function requestedUint256(bytes32 _requestId, uint256 _value) public { - requestId = _requestId; + s_requestId = _requestId; setUint256(_value); } } diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousChainlink.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlink.sol similarity index 91% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousChainlink.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlink.sol index 5cc343aa7f4..11c863fbb98 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousChainlink.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlink.sol @@ -1,7 +1,7 @@ pragma solidity ^0.8.0; -import {CBORChainlink as CBOR_Chainlink} from "../../../../vendor/CBORChainlink.sol"; -import {BufferChainlink as Buffer_Chainlink} from "../../../../vendor/BufferChainlink.sol"; +import {CBORChainlink as CBOR_Chainlink} from "../../../vendor/CBORChainlink.sol"; +import {BufferChainlink as Buffer_Chainlink} from "../../../vendor/BufferChainlink.sol"; // solhint-disable library MaliciousChainlink { diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousChainlinked.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlinked.sol similarity index 80% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousChainlinked.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlinked.sol index 722fbdd599b..989c39c18be 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousChainlinked.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlinked.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; import {MaliciousChainlink} from "./MaliciousChainlink.sol"; import {Chainlinked, Chainlink} from "./Chainlinked.sol"; -import {LinkTokenInterface} from "../../../../shared/interfaces/LinkTokenInterface.sol"; +import {LinkTokenInterface} from "../../../shared/interfaces/LinkTokenInterface.sol"; // solhint-disable contract MaliciousChainlinked is Chainlinked { @@ -10,8 +10,8 @@ contract MaliciousChainlinked is Chainlinked { using MaliciousChainlink for MaliciousChainlink.WithdrawRequest; using Chainlink for Chainlink.Request; - uint256 private maliciousRequests = 1; - mapping(bytes32 => address) private maliciousPendingRequests; + uint256 private s_maliciousRequests = 1; + mapping(bytes32 => address) private s_maliciousPendingRequests; function newWithdrawRequest( bytes32 _specId, @@ -27,31 +27,31 @@ contract MaliciousChainlinked is Chainlinked { Chainlink.Request memory _req, uint256 _amount ) internal returns (bytes32 requestId) { - requestId = keccak256(abi.encodePacked(_target, maliciousRequests)); - _req.nonce = maliciousRequests; - maliciousPendingRequests[requestId] = oracleAddress(); + requestId = keccak256(abi.encodePacked(_target, s_maliciousRequests)); + _req.nonce = s_maliciousRequests; + s_maliciousPendingRequests[requestId] = oracleAddress(); emit ChainlinkRequested(requestId); LinkTokenInterface link = LinkTokenInterface(chainlinkToken()); require( link.transferAndCall(oracleAddress(), _amount, encodeTargetRequest(_req)), "Unable to transferAndCall to oracle" ); - maliciousRequests += 1; + s_maliciousRequests += 1; return requestId; } function chainlinkPriceRequest(Chainlink.Request memory _req, uint256 _amount) internal returns (bytes32 requestId) { - requestId = keccak256(abi.encodePacked(this, maliciousRequests)); - _req.nonce = maliciousRequests; - maliciousPendingRequests[requestId] = oracleAddress(); + requestId = keccak256(abi.encodePacked(this, s_maliciousRequests)); + _req.nonce = s_maliciousRequests; + s_maliciousPendingRequests[requestId] = oracleAddress(); emit ChainlinkRequested(requestId); LinkTokenInterface link = LinkTokenInterface(chainlinkToken()); require( link.transferAndCall(oracleAddress(), _amount, encodePriceRequest(_req)), "Unable to transferAndCall to oracle" ); - maliciousRequests += 1; + s_maliciousRequests += 1; return requestId; } @@ -60,16 +60,16 @@ contract MaliciousChainlinked is Chainlinked { MaliciousChainlink.WithdrawRequest memory _req, uint256 _wei ) internal returns (bytes32 requestId) { - requestId = keccak256(abi.encodePacked(this, maliciousRequests)); - _req.nonce = maliciousRequests; - maliciousPendingRequests[requestId] = oracleAddress(); + requestId = keccak256(abi.encodePacked(this, s_maliciousRequests)); + _req.nonce = s_maliciousRequests; + s_maliciousPendingRequests[requestId] = oracleAddress(); emit ChainlinkRequested(requestId); LinkTokenInterface link = LinkTokenInterface(chainlinkToken()); require( link.transferAndCall(oracleAddress(), _wei, encodeWithdrawRequest(_req)), "Unable to transferAndCall to oracle" ); - maliciousRequests += 1; + s_maliciousRequests += 1; return requestId; } diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousConsumer.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousConsumer.sol similarity index 92% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousConsumer.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousConsumer.sol index 003e628880f..842eec90542 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousConsumer.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousConsumer.sol @@ -5,7 +5,7 @@ import {Chainlinked, Chainlink} from "./Chainlinked.sol"; // solhint-disable contract MaliciousConsumer is Chainlinked { uint256 private constant ORACLE_PAYMENT = 1 ether; - uint256 private expiration; + uint256 private s_expiration; constructor(address _link, address _oracle) public payable { setLinkToken(_link); @@ -16,7 +16,7 @@ contract MaliciousConsumer is Chainlinked { function requestData(bytes32 _id, bytes memory _callbackFunc) public { Chainlink.Request memory req = newRequest(_id, address(this), bytes4(keccak256(_callbackFunc))); - expiration = block.timestamp + 5 minutes; + s_expiration = block.timestamp + 5 minutes; chainlinkRequest(req, ORACLE_PAYMENT); } @@ -25,7 +25,7 @@ contract MaliciousConsumer is Chainlinked { } function cancelRequestOnFulfill(bytes32 _requestId, bytes32) public { - _cancelChainlinkRequest(_requestId, ORACLE_PAYMENT, this.cancelRequestOnFulfill.selector, expiration); + _cancelChainlinkRequest(_requestId, ORACLE_PAYMENT, this.cancelRequestOnFulfill.selector, s_expiration); } function remove() public { diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousMultiWordConsumer.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousMultiWordConsumer.sol similarity index 94% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousMultiWordConsumer.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousMultiWordConsumer.sol index 272361f2dda..d9d14cb3d43 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousMultiWordConsumer.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousMultiWordConsumer.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {ChainlinkClient} from "../../../../ChainlinkClient.sol"; -import {Chainlink} from "../../../../Chainlink.sol"; +import {ChainlinkClient} from "../../../ChainlinkClient.sol"; +import {Chainlink} from "../../../Chainlink.sol"; contract MaliciousMultiWordConsumer is ChainlinkClient { uint256 private constant ORACLE_PAYMENT = 1 ether; diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousRequester.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousRequester.sol similarity index 95% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousRequester.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousRequester.sol index 9b19653722c..c01c8a60bb7 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousRequester.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousRequester.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; import {MaliciousChainlink} from "./MaliciousChainlink.sol"; import {MaliciousChainlinked, Chainlink} from "./MaliciousChainlinked.sol"; -import {ChainlinkRequestInterface} from "../../../../interfaces/ChainlinkRequestInterface.sol"; +import {ChainlinkRequestInterface} from "../../../interfaces/ChainlinkRequestInterface.sol"; contract MaliciousRequester is MaliciousChainlinked { uint256 private constant ORACLE_PAYMENT = 1 ether; diff --git a/contracts/src/v0.8/operatorforwarder/test/testhelpers/MockReceiver.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MockReceiver.sol new file mode 100644 index 00000000000..4e825b4505f --- /dev/null +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MockReceiver.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +contract MockReceiver { + uint256 private s_value; + + function receiveData(uint256 _value) public { + s_value = _value; + } + + function revertMessage() public pure { + revert("test revert message"); + } + + function getValue() external view returns (uint256) { + return s_value; + } +} diff --git a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MultiWordConsumer.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MultiWordConsumer.sol similarity index 81% rename from contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MultiWordConsumer.sol rename to contracts/src/v0.8/operatorforwarder/test/testhelpers/MultiWordConsumer.sol index ce2bf1907c5..fe249831fef 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/test/testhelpers/MultiWordConsumer.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MultiWordConsumer.sol @@ -1,21 +1,21 @@ pragma solidity ^0.8.0; -import {ChainlinkClient, ChainlinkRequestInterface, LinkTokenInterface} from "../../../../ChainlinkClient.sol"; -import {Chainlink} from "../../../../Chainlink.sol"; +import {ChainlinkClient, ChainlinkRequestInterface, LinkTokenInterface} from "../../../ChainlinkClient.sol"; +import {Chainlink} from "../../../Chainlink.sol"; contract MultiWordConsumer is ChainlinkClient { using Chainlink for Chainlink.Request; bytes32 internal s_specId; - bytes public currentPrice; + bytes internal s_currentPrice; - bytes32 public usd; - bytes32 public eur; - bytes32 public jpy; + bytes32 private s_usd; + bytes32 private s_eur; + bytes32 private s_jpy; - uint256 public usdInt; - uint256 public eurInt; - uint256 public jpyInt; + uint256 private s_usdInt; + uint256 private s_eurInt; + uint256 private s_jpyInt; event RequestFulfilled( bytes32 indexed requestId, // User-defined ID @@ -100,9 +100,9 @@ contract MultiWordConsumer is ChainlinkClient { bytes32 _jpy ) public recordChainlinkFulfillment(_requestId) { emit RequestMultipleFulfilled(_requestId, _usd, _eur, _jpy); - usd = _usd; - eur = _eur; - jpy = _jpy; + s_usd = _usd; + s_eur = _eur; + s_jpy = _jpy; } function fulfillMultipleParametersWithCustomURLs( @@ -112,17 +112,33 @@ contract MultiWordConsumer is ChainlinkClient { uint256 _jpy ) public recordChainlinkFulfillment(_requestId) { emit RequestMultipleFulfilledWithCustomURLs(_requestId, _usd, _eur, _jpy); - usdInt = _usd; - eurInt = _eur; - jpyInt = _jpy; + s_usdInt = _usd; + s_eurInt = _eur; + s_jpyInt = _jpy; } function fulfillBytes(bytes32 _requestId, bytes memory _price) public recordChainlinkFulfillment(_requestId) { emit RequestFulfilled(_requestId, _price); - currentPrice = _price; + s_currentPrice = _price; } function publicGetNextRequestCount() external view returns (uint256) { return _getNextRequestCount(); } + + function getCurrentPrice() public view returns (bytes memory _value) { + return s_currentPrice; + } + + function usd() public view returns (bytes32 _value) { + return s_usd; + } + + function eur() public view returns (bytes32 _value) { + return s_eur; + } + + function jpy() public view returns (bytes32 _value) { + return s_jpy; + } } diff --git a/contracts/test/v0.8/ChainlinkClient.test.ts b/contracts/test/v0.8/ChainlinkClient.test.ts index b483e890a6b..c5691211c1a 100644 --- a/contracts/test/v0.8/ChainlinkClient.test.ts +++ b/contracts/test/v0.8/ChainlinkClient.test.ts @@ -27,15 +27,15 @@ before(async () => { roles.defaultAccount, ) emptyOracleFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/test/testhelpers/EmptyOracle.sol:EmptyOracle', + 'src/v0.8/operatorforwarder/test/testhelpers/EmptyOracle.sol:EmptyOracle', roles.defaultAccount, ) getterSetterFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/test/testhelpers/GetterSetter.sol:GetterSetter', + 'src/v0.8/operatorforwarder/test/testhelpers/GetterSetter.sol:GetterSetter', roles.defaultAccount, ) operatorFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/Operator.sol:Operator', + 'src/v0.8/operatorforwarder/Operator.sol:Operator', roles.defaultAccount, ) linkTokenFactory = await ethers.getContractFactory( diff --git a/contracts/test/v0.8/operatorforwarder/AuthorizedForwarder.test.ts b/contracts/test/v0.8/operatorforwarder/AuthorizedForwarder.test.ts index 2d6329e221d..d4e1918c976 100644 --- a/contracts/test/v0.8/operatorforwarder/AuthorizedForwarder.test.ts +++ b/contracts/test/v0.8/operatorforwarder/AuthorizedForwarder.test.ts @@ -18,7 +18,7 @@ before(async () => { roles = users.roles getterSetterFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/test/testhelpers/GetterSetter.sol:GetterSetter', + 'src/v0.8/operatorforwarder/test/testhelpers/GetterSetter.sol:GetterSetter', roles.defaultAccount, ) brokenFactory = await ethers.getContractFactory( @@ -26,7 +26,7 @@ before(async () => { roles.defaultAccount, ) forwarderFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/AuthorizedForwarder.sol:AuthorizedForwarder', + 'src/v0.8/operatorforwarder/AuthorizedForwarder.sol:AuthorizedForwarder', roles.defaultAccount, ) linkTokenFactory = await ethers.getContractFactory( diff --git a/contracts/test/v0.8/operatorforwarder/Operator.test.ts b/contracts/test/v0.8/operatorforwarder/Operator.test.ts index 0d75d8530a4..6fb8768f54a 100644 --- a/contracts/test/v0.8/operatorforwarder/Operator.test.ts +++ b/contracts/test/v0.8/operatorforwarder/Operator.test.ts @@ -50,31 +50,31 @@ before(async () => { roles = users.roles basicConsumerFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/test/testhelpers/BasicConsumer.sol:BasicConsumer', + 'src/v0.8/operatorforwarder/test/testhelpers/BasicConsumer.sol:BasicConsumer', ) multiWordConsumerFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/test/testhelpers/MultiWordConsumer.sol:MultiWordConsumer', + 'src/v0.8/operatorforwarder/test/testhelpers/MultiWordConsumer.sol:MultiWordConsumer', ) gasGuzzlingConsumerFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/test/testhelpers/GasGuzzlingConsumer.sol:GasGuzzlingConsumer', + 'src/v0.8/operatorforwarder/test/testhelpers/GasGuzzlingConsumer.sol:GasGuzzlingConsumer', ) getterSetterFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/test/testhelpers/GetterSetter.sol:GetterSetter', + 'src/v0.8/operatorforwarder/test/testhelpers/GetterSetter.sol:GetterSetter', ) maliciousRequesterFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousRequester.sol:MaliciousRequester', + 'src/v0.8/operatorforwarder/test/testhelpers/MaliciousRequester.sol:MaliciousRequester', ) maliciousConsumerFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousConsumer.sol:MaliciousConsumer', + 'src/v0.8/operatorforwarder/test/testhelpers/MaliciousConsumer.sol:MaliciousConsumer', ) maliciousMultiWordConsumerFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/test/testhelpers/MaliciousMultiWordConsumer.sol:MaliciousMultiWordConsumer', + 'src/v0.8/operatorforwarder/test/testhelpers/MaliciousMultiWordConsumer.sol:MaliciousMultiWordConsumer', ) operatorFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/Operator.sol:Operator', + 'src/v0.8/operatorforwarder/Operator.sol:Operator', ) forwarderFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/AuthorizedForwarder.sol:AuthorizedForwarder', + 'src/v0.8/operatorforwarder/AuthorizedForwarder.sol:AuthorizedForwarder', ) linkTokenFactory = await ethers.getContractFactory( 'src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol:LinkTokenTestHelper', @@ -1076,7 +1076,7 @@ describe('Operator', () => { .connect(roles.oracleNode) .fulfillOracleRequest(...convertFufillParams(request, response)) - const currentValue = await basicConsumer.currentPrice() + const currentValue = await basicConsumer.getCurrentPrice() assert.equal(response, ethers.utils.parseBytes32String(currentValue)) }) @@ -1105,7 +1105,7 @@ describe('Operator', () => { .fulfillOracleRequest(...convertFufillParams(request, response2)), ) - const currentValue = await basicConsumer.currentPrice() + const currentValue = await basicConsumer.getCurrentPrice() assert.equal(response, ethers.utils.parseBytes32String(currentValue)) }) }) @@ -1419,7 +1419,7 @@ describe('Operator', () => { }) describe('#fulfillOracleRequest2', () => { - describe('single word fulfils', () => { + describe('single word fulfills', () => { const response = 'Hi mom!' const responseTypes = ['bytes32'] const responseValues = [toBytes32String(response)] @@ -1528,7 +1528,7 @@ describe('Operator', () => { ), ) - const currentValue = await basicConsumer.currentPrice() + const currentValue = await basicConsumer.getCurrentPrice() assert.equal( response, ethers.utils.parseBytes32String(currentValue), @@ -1576,7 +1576,7 @@ describe('Operator', () => { ), ) - const currentValue = await basicConsumer.currentPrice() + const currentValue = await basicConsumer.getCurrentPrice() assert.equal( response, ethers.utils.parseBytes32String(currentValue), @@ -2024,7 +2024,7 @@ describe('Operator', () => { }) }) - describe('multi word fulfils', () => { + describe('multi word fulfills', () => { describe('one bytes parameter', () => { const response = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.\ @@ -2149,7 +2149,7 @@ describe('Operator', () => { ), ) - const currentValue = await multiConsumer.currentPrice() + const currentValue = await multiConsumer.getCurrentPrice() assert.equal(response, ethers.utils.toUtf8String(currentValue)) }) @@ -2195,7 +2195,7 @@ describe('Operator', () => { ), ) - const currentValue = await multiConsumer.currentPrice() + const currentValue = await multiConsumer.getCurrentPrice() assert.equal(response, ethers.utils.toUtf8String(currentValue)) }) }) diff --git a/contracts/test/v0.8/operatorforwarder/OperatorFactory.test.ts b/contracts/test/v0.8/operatorforwarder/OperatorFactory.test.ts index b9a0fe508b0..b54a75c2c0d 100644 --- a/contracts/test/v0.8/operatorforwarder/OperatorFactory.test.ts +++ b/contracts/test/v0.8/operatorforwarder/OperatorFactory.test.ts @@ -20,15 +20,15 @@ before(async () => { roles.defaultAccount, ) operatorGeneratorFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/OperatorFactory.sol:OperatorFactory', + 'src/v0.8/operatorforwarder/OperatorFactory.sol:OperatorFactory', roles.defaultAccount, ) operatorFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/Operator.sol:Operator', + 'src/v0.8/operatorforwarder/Operator.sol:Operator', roles.defaultAccount, ) forwarderFactory = await ethers.getContractFactory( - 'src/v0.8/operatorforwarder/dev/AuthorizedForwarder.sol:AuthorizedForwarder', + 'src/v0.8/operatorforwarder/AuthorizedForwarder.sol:AuthorizedForwarder', roles.defaultAccount, ) }) From 8cf34d2d91bf92aeb373f349e5fc5aaf73111e3e Mon Sep 17 00:00:00 2001 From: HenryNguyen5 <6404866+HenryNguyen5@users.noreply.github.com> Date: Thu, 2 May 2024 09:10:33 -0400 Subject: [PATCH 29/45] Autogen solidity wrappers (#13062) --- .../detect-solidity-file-changes/action.yml | 36 ++++++++ .github/workflows/solidity-wrappers.yml | 82 +++++++++++++++++++ .github/workflows/solidity.yml | 33 +------- 3 files changed, 122 insertions(+), 29 deletions(-) create mode 100644 .github/actions/detect-solidity-file-changes/action.yml create mode 100644 .github/workflows/solidity-wrappers.yml diff --git a/.github/actions/detect-solidity-file-changes/action.yml b/.github/actions/detect-solidity-file-changes/action.yml new file mode 100644 index 00000000000..37cb871d68d --- /dev/null +++ b/.github/actions/detect-solidity-file-changes/action.yml @@ -0,0 +1,36 @@ +name: 'Detect Changes Composite Action' +description: 'Detects changes in solidity files and fails if read-only files are modified.' +outputs: + changes: + description: 'Whether or not changes were detected' + value: ${{ steps.changed_files.outputs.src }} +runs: + using: 'composite' + steps: + + - name: Filter paths + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + id: changed_files + with: + list-files: 'csv' + filters: | + src: + - 'contracts/**/*' + - '.github/workflows/solidity.yml' + - '.github/workflows/solidity-foundry.yml' + - '.github/workflows/solidity-wrappers.yml' + read_only_sol: + - 'contracts/src/v0.8/interfaces/**/*' + - 'contracts/src/v0.8/automation/v1_2/**/*' + - 'contracts/src/v0.8/automation/v1_3/**/*' + - 'contracts/src/v0.8/automation/v2_0/**/*' + + - name: Fail if read-only files have changed + if: ${{ steps.changed_files.outputs.read_only_sol == 'true' }} + shell: bash + run: | + echo "One or more read-only Solidity file(s) has changed." + for file in ${{ steps.changed_files.outputs.read_only_sol_files }}; do + echo "$file was changed" + done + exit 1 diff --git a/.github/workflows/solidity-wrappers.yml b/.github/workflows/solidity-wrappers.yml new file mode 100644 index 00000000000..56528611f36 --- /dev/null +++ b/.github/workflows/solidity-wrappers.yml @@ -0,0 +1,82 @@ +name: Solidity Wrappers +# This is its own workflow file rather than being merged into "solidity.yml" to avoid over complicating the conditionals +# used for job execution. The jobs in "solidity.yml" are configured around push events, whereas +# we only want to generate gethwrappers during pull requests. +on: + pull_request: + types: + - opened + - synchronize + - reopened + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + changes: + name: Detect changes + runs-on: ubuntu-latest + outputs: + changes: ${{ steps.ch.outputs.changes }} + steps: + - name: Checkout the repo + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + - name: Detect changes + id: ch + uses: ./.github/actions/detect-solidity-file-changes + + # On a pull request event, make updates to gethwrappers if there are changes. + update-wrappers: + needs: [changes] + if: needs.changes.outputs.changes == 'true' + name: Update Wrappers + permissions: + actions: read + id-token: write + contents: read + runs-on: ubuntu22.04-8cores-32GB + steps: + - name: Checkout the repo + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + + - name: Setup Go + uses: ./.github/actions/setup-go + + - name: Setup NodeJS + uses: ./.github/actions/setup-nodejs + with: + prod: "true" + + - name: Run native compile and generate wrappers + run: make wrappers-all + working-directory: ./contracts + + - name: Assume role capable of dispatching action + uses: smartcontractkit/.github/actions/setup-github-token@9e7cc0779934cae4a9028b8588c9adb64d8ce68c # setup-github-token@0.1.0 + id: get-gh-token + with: + aws-role-arn: ${{ secrets.AWS_OIDC_CHAINLINK_CI_AUTO_PR_TOKEN_ISSUER_ROLE_ARN }} + aws-lambda-url: ${{ secrets.AWS_INFRA_RELENG_TOKEN_ISSUER_LAMBDA_URL }} + aws-region: ${{ secrets.AWS_REGION }} + + - name: Commit any wrapper changes + uses: planetscale/ghcommit-action@21a8cda29f55e5cc2cdae0cdbdd08e38dd148c25 # v0.1.37 + with: + commit_message: "Update gethwrappers" + repo: ${{ github.repository }} + branch: ${{ github.head_ref }} + file_pattern: "core/gethwrappers/**/generated/*.go core/gethwrappers/**/generated-wrapper-dependency-versions-do-not-edit.txt" + env: + GITHUB_TOKEN: ${{ steps.get-gh-token.outputs.access-token }} + + - name: Collect Metrics + id: collect-gha-metrics + uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 + with: + id: solidity-update-wrappers + org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} + basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} + hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} + this-job-name: Update Wrappers + continue-on-error: true diff --git a/.github/workflows/solidity.yml b/.github/workflows/solidity.yml index b2dc3d4153c..22ed53e72bc 100644 --- a/.github/workflows/solidity.yml +++ b/.github/workflows/solidity.yml @@ -13,33 +13,13 @@ jobs: name: Detect changes runs-on: ubuntu-latest outputs: - changes: ${{ steps.changes.outputs.src }} + changes: ${{ steps.ch.outputs.changes }} steps: - name: Checkout the repo uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - id: changes - with: - list-files: "csv" - filters: | - src: - - 'contracts/**/*' - - '.github/workflows/solidity.yml' - - '.github/workflows/solidity-foundry.yml' - read_only_sol: - - 'contracts/src/v0.8/interfaces/**/*' - - 'contracts/src/v0.8/automation/v1_2/**/*' - - 'contracts/src/v0.8/automation/v1_3/**/*' - - 'contracts/src/v0.8/automation/v2_0/**/*' - - - name: Fail if read-only files have changed - if: ${{ steps.changes.outputs.read_only_sol == 'true' }} - run: | - echo "One or more read-only Solidity file(s) has changed." - for file in ${{ steps.changes.outputs.read_only_sol_files }}; do - echo "$file was changed" - done - exit 1 + - name: Detect changes + id: ch + uses: ./.github/actions/detect-solidity-file-changes tag-check: needs: [changes] @@ -116,11 +96,6 @@ jobs: - name: Check if Go solidity wrappers are updated if: ${{ needs.changes.outputs.changes == 'true' }} run: git diff --minimal --color --exit-code | diff-so-fancy - - name: Comment on fix instructions - env: - GITHUB_TOKEN: ${{ github.token }} - if: ${{ failure() }} - run: gh pr comment -b 'Go solidity wrappers are out-of-date, regenerate them via the `make wrappers-all` command' - name: Collect Metrics id: collect-gha-metrics uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 From 1e50baefe7be679f1da44612814d2fdef129abb1 Mon Sep 17 00:00:00 2001 From: Lee Yik Jiun Date: Thu, 2 May 2024 23:44:14 +0800 Subject: [PATCH 30/45] Add vrf coordinator v2.5 mock (#12873) * Add vrf coordinator v2.5 mock * Fix natspec complaining about inheritdoc references inexistent contract --- .../v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol | 268 +++++++++ .../vrf/test/VRFCoordinatorV2_5Mock.t.sol | 511 ++++++++++++++++++ .../vrf/testhelpers/VRFConsumerV2Plus.sol | 55 ++ 3 files changed, 834 insertions(+) create mode 100644 contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol create mode 100644 contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5Mock.t.sol create mode 100644 contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2Plus.sol diff --git a/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol b/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol new file mode 100644 index 00000000000..ac95c1e3177 --- /dev/null +++ b/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol @@ -0,0 +1,268 @@ +// SPDX-License-Identifier: MIT +// A mock for testing code that relies on VRFCoordinatorV2_5. +pragma solidity ^0.8.19; + +import {IVRFCoordinatorV2Plus, IVRFSubscriptionV2Plus} from "../dev/interfaces/IVRFCoordinatorV2Plus.sol"; +import {VRFV2PlusClient} from "../dev/libraries/VRFV2PlusClient.sol"; +import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; +import {VRFConsumerBaseV2Plus} from "../dev/VRFConsumerBaseV2Plus.sol"; + +contract VRFCoordinatorV2_5Mock is SubscriptionAPI, IVRFCoordinatorV2Plus { + uint96 public immutable i_base_fee; + uint96 public immutable i_gas_price; + int256 public immutable i_wei_per_unit_link; + + error InvalidRequest(); + error InvalidRandomWords(); + error InvalidExtraArgsTag(); + error NotImplemented(); + + event RandomWordsRequested( + bytes32 indexed keyHash, + uint256 requestId, + uint256 preSeed, + uint256 indexed subId, + uint16 minimumRequestConfirmations, + uint32 callbackGasLimit, + uint32 numWords, + bytes extraArgs, + address indexed sender + ); + event RandomWordsFulfilled( + uint256 indexed requestId, + uint256 outputSeed, + uint256 indexed subId, + uint96 payment, + bool nativePayment, + bool success, + bool onlyPremium + ); + event ConfigSet(); + + uint64 internal s_currentSubId; + uint256 internal s_nextRequestId = 1; + uint256 internal s_nextPreSeed = 100; + + struct Request { + uint256 subId; + uint32 callbackGasLimit; + uint32 numWords; + bytes extraArgs; + } + mapping(uint256 => Request) internal s_requests; /* requestId */ /* request */ + + constructor(uint96 _baseFee, uint96 _gasPrice, int256 _weiPerUnitLink) SubscriptionAPI() { + i_base_fee = _baseFee; + i_gas_price = _gasPrice; + i_wei_per_unit_link = _weiPerUnitLink; + setConfig(); + } + + /** + * @notice Sets the configuration of the vrfv2 mock coordinator + */ + function setConfig() public onlyOwner { + s_config = Config({ + minimumRequestConfirmations: 0, + maxGasLimit: 0, + stalenessSeconds: 0, + gasAfterPaymentCalculation: 0, + reentrancyLock: false, + fulfillmentFlatFeeNativePPM: 0, + fulfillmentFlatFeeLinkDiscountPPM: 0, + nativePremiumPercentage: 0, + linkPremiumPercentage: 0 + }); + emit ConfigSet(); + } + + function consumerIsAdded(uint256 _subId, address _consumer) public view returns (bool) { + return s_consumers[_consumer][_subId].active; + } + + modifier onlyValidConsumer(uint256 _subId, address _consumer) { + if (!consumerIsAdded(_subId, _consumer)) { + revert InvalidConsumer(_subId, _consumer); + } + _; + } + + /** + * @notice fulfillRandomWords fulfills the given request, sending the random words to the supplied + * @notice consumer. + * + * @dev This mock uses a simplified formula for calculating payment amount and gas usage, and does + * @dev not account for all edge cases handled in the real VRF coordinator. When making requests + * @dev against the real coordinator a small amount of additional LINK is required. + * + * @param _requestId the request to fulfill + * @param _consumer the VRF randomness consumer to send the result to + */ + function fulfillRandomWords(uint256 _requestId, address _consumer) external nonReentrant { + fulfillRandomWordsWithOverride(_requestId, _consumer, new uint256[](0)); + } + + /** + * @notice fulfillRandomWordsWithOverride allows the user to pass in their own random words. + * + * @param _requestId the request to fulfill + * @param _consumer the VRF randomness consumer to send the result to + * @param _words user-provided random words + */ + function fulfillRandomWordsWithOverride(uint256 _requestId, address _consumer, uint256[] memory _words) public { + uint256 startGas = gasleft(); + if (s_requests[_requestId].subId == 0) { + revert InvalidRequest(); + } + Request memory req = s_requests[_requestId]; + + if (_words.length == 0) { + _words = new uint256[](req.numWords); + for (uint256 i = 0; i < req.numWords; i++) { + _words[i] = uint256(keccak256(abi.encode(_requestId, i))); + } + } else if (_words.length != req.numWords) { + revert InvalidRandomWords(); + } + + VRFConsumerBaseV2Plus v; + bytes memory callReq = abi.encodeWithSelector(v.rawFulfillRandomWords.selector, _requestId, _words); + s_config.reentrancyLock = true; + // solhint-disable-next-line avoid-low-level-calls, no-unused-vars + (bool success, ) = _consumer.call{gas: req.callbackGasLimit}(callReq); + s_config.reentrancyLock = false; + + bool nativePayment = uint8(req.extraArgs[req.extraArgs.length - 1]) == 1; + + uint256 rawPayment = i_base_fee + ((startGas - gasleft()) * i_gas_price); + if (!nativePayment) { + rawPayment = (1e18 * rawPayment) / uint256(i_wei_per_unit_link); + } + uint96 payment = uint96(rawPayment); + + _chargePayment(payment, nativePayment, req.subId); + + delete (s_requests[_requestId]); + emit RandomWordsFulfilled(_requestId, _requestId, req.subId, payment, nativePayment, success, false); + } + + function _chargePayment(uint96 payment, bool nativePayment, uint256 subId) internal { + Subscription storage subcription = s_subscriptions[subId]; + if (nativePayment) { + uint96 prevBal = subcription.nativeBalance; + if (prevBal < payment) { + revert InsufficientBalance(); + } + subcription.nativeBalance = prevBal - payment; + s_withdrawableNative += payment; + } else { + uint96 prevBal = subcription.balance; + if (prevBal < payment) { + revert InsufficientBalance(); + } + subcription.balance = prevBal - payment; + s_withdrawableTokens += payment; + } + } + + /** + * @notice fundSubscription allows funding a subscription with an arbitrary amount for testing. + * + * @param _subId the subscription to fund + * @param _amount the amount to fund + */ + function fundSubscription(uint256 _subId, uint256 _amount) public { + if (s_subscriptionConfigs[_subId].owner == address(0)) { + revert InvalidSubscription(); + } + uint256 oldBalance = s_subscriptions[_subId].balance; + s_subscriptions[_subId].balance += uint96(_amount); + s_totalBalance += uint96(_amount); + emit SubscriptionFunded(_subId, oldBalance, oldBalance + _amount); + } + + /// @dev Convert the extra args bytes into a struct + /// @param extraArgs The extra args bytes + /// @return The extra args struct + function _fromBytes(bytes calldata extraArgs) internal pure returns (VRFV2PlusClient.ExtraArgsV1 memory) { + if (extraArgs.length == 0) { + return VRFV2PlusClient.ExtraArgsV1({nativePayment: false}); + } + if (bytes4(extraArgs) != VRFV2PlusClient.EXTRA_ARGS_V1_TAG) revert InvalidExtraArgsTag(); + return abi.decode(extraArgs[4:], (VRFV2PlusClient.ExtraArgsV1)); + } + + function requestRandomWords( + VRFV2PlusClient.RandomWordsRequest calldata _req + ) external override nonReentrant onlyValidConsumer(_req.subId, msg.sender) returns (uint256) { + uint256 subId = _req.subId; + if (s_subscriptionConfigs[subId].owner == address(0)) { + revert InvalidSubscription(); + } + + uint256 requestId = s_nextRequestId++; + uint256 preSeed = s_nextPreSeed++; + + bytes memory extraArgsBytes = VRFV2PlusClient._argsToBytes(_fromBytes(_req.extraArgs)); + s_requests[requestId] = Request({ + subId: _req.subId, + callbackGasLimit: _req.callbackGasLimit, + numWords: _req.numWords, + extraArgs: _req.extraArgs + }); + + emit RandomWordsRequested( + _req.keyHash, + requestId, + preSeed, + _req.subId, + _req.requestConfirmations, + _req.callbackGasLimit, + _req.numWords, + extraArgsBytes, + msg.sender + ); + return requestId; + } + + /** + * @inheritdoc IVRFSubscriptionV2Plus + */ + function removeConsumer( + uint256 _subId, + address _consumer + ) external override onlySubOwner(_subId) onlyValidConsumer(_subId, _consumer) nonReentrant { + if (!s_consumers[_consumer][_subId].active) { + revert InvalidConsumer(_subId, _consumer); + } + address[] memory consumers = s_subscriptionConfigs[_subId].consumers; + uint256 lastConsumerIndex = consumers.length - 1; + for (uint256 i = 0; i < consumers.length; ++i) { + if (consumers[i] == _consumer) { + address last = consumers[lastConsumerIndex]; + s_subscriptionConfigs[_subId].consumers[i] = last; + s_subscriptionConfigs[_subId].consumers.pop(); + break; + } + } + s_consumers[_consumer][_subId].active = false; + emit SubscriptionConsumerRemoved(_subId, _consumer); + } + + /** + * @inheritdoc IVRFSubscriptionV2Plus + */ + function cancelSubscription(uint256 _subId, address _to) external override onlySubOwner(_subId) nonReentrant { + (uint96 balance, uint96 nativeBalance) = _deleteSubscription(_subId); + + (bool success, ) = _to.call{value: uint256(nativeBalance)}(""); + if (!success) { + revert FailedToSendNative(); + } + emit SubscriptionCanceled(_subId, _to, balance, nativeBalance); + } + + function pendingRequestExists(uint256 /*subId*/) public pure override returns (bool) { + revert NotImplemented(); + } +} diff --git a/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5Mock.t.sol b/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5Mock.t.sol new file mode 100644 index 00000000000..75c763c88cb --- /dev/null +++ b/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5Mock.t.sol @@ -0,0 +1,511 @@ +pragma solidity 0.8.19; + +import "./BaseTest.t.sol"; +import {VRFV2PlusClient} from "../dev/libraries/VRFV2PlusClient.sol"; +import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; +import {VRFCoordinatorV2_5Mock} from "../mocks/VRFCoordinatorV2_5Mock.sol"; +import {VRFConsumerV2Plus} from "../testhelpers/VRFConsumerV2Plus.sol"; +import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; + +contract VRFCoordinatorV2_5MockTest is BaseTest { + MockLinkToken internal s_linkToken; + VRFCoordinatorV2_5Mock internal s_vrfCoordinatorV2_5Mock; + VRFConsumerV2Plus internal s_vrfConsumerV2Plus; + address internal s_subOwner = address(1234); + + bytes32 internal constant KEY_HASH = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528"; + + uint32 internal constant DEFAULT_CALLBACK_GAS_LIMIT = 500_000; + uint16 internal constant DEFAULT_REQUEST_CONFIRMATIONS = 3; + uint32 internal constant DEFAULT_NUM_WORDS = 1; + + uint96 internal constant oneNative = 1 ether; + uint96 internal constant twoLink = 2 ether; + + event SubscriptionCreated(uint256 indexed subId, address owner); + event SubscriptionFunded(uint256 indexed subId, uint256 oldBalance, uint256 newBalance); + event SubscriptionFundedWithNative(uint256 indexed subId, uint256 oldNativeBalance, uint256 newNativeBalance); + event SubscriptionConsumerAdded(uint256 indexed subId, address consumer); + event SubscriptionConsumerRemoved(uint256 indexed subId, address consumer); + event SubscriptionCanceled(uint256 indexed subId, address to, uint256 amountLink, uint256 amountNative); + + event RandomWordsRequested( + bytes32 indexed keyHash, + uint256 requestId, + uint256 preSeed, + uint256 indexed subId, + uint16 minimumRequestConfirmations, + uint32 callbackGasLimit, + uint32 numWords, + bytes extraArgs, + address indexed sender + ); + event RandomWordsFulfilled( + uint256 indexed requestId, + uint256 outputSeed, + uint256 indexed subId, + uint96 payment, + bool nativePayment, + bool success, + bool onlyPremium + ); + + function setUp() public override { + BaseTest.setUp(); + + // Fund our users. + vm.roll(1); + vm.deal(OWNER, 10_000 ether); + vm.deal(s_subOwner, 20 ether); + + // Deploy link token and link/eth feed. + s_linkToken = new MockLinkToken(); + + // Deploy coordinator and consumer. + s_vrfCoordinatorV2_5Mock = new VRFCoordinatorV2_5Mock(0.002 ether, 40 gwei, 0.004 ether); + address coordinatorAddr = address(s_vrfCoordinatorV2_5Mock); + s_vrfConsumerV2Plus = new VRFConsumerV2Plus(coordinatorAddr, address(s_linkToken)); + + s_vrfCoordinatorV2_5Mock.setConfig(); + } + + function test_CreateSubscription() public { + vm.startPrank(s_subOwner); + uint256 expectedSubId = uint256( + keccak256( + abi.encodePacked( + s_subOwner, + blockhash(block.number - 1), + address(s_vrfCoordinatorV2_5Mock), + s_vrfCoordinatorV2_5Mock.s_currentSubNonce() + ) + ) + ); + vm.expectEmit( + true, // no first indexed topic + false, // no second indexed topic + false, // no third indexed topic + true // check data (target coordinator address) + ); + emit SubscriptionCreated(expectedSubId, s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + assertEq(subId, expectedSubId); + + ( + uint96 balance, + uint96 nativeBalance, + uint64 reqCount, + address owner, + address[] memory consumers + ) = s_vrfCoordinatorV2_5Mock.getSubscription(subId); + assertEq(balance, 0); + assertEq(nativeBalance, 0); + assertEq(reqCount, 0); + assertEq(owner, s_subOwner); + assertEq(consumers.length, 0); + vm.stopPrank(); + } + + function test_AddConsumer() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + vm.expectEmit(true, false, false, true); + emit SubscriptionConsumerAdded(subId, address(s_vrfConsumerV2Plus)); + s_vrfCoordinatorV2_5Mock.addConsumer(subId, address(s_vrfConsumerV2Plus)); + + (uint96 balance, , uint64 reqCount, address owner, address[] memory consumers) = s_vrfCoordinatorV2_5Mock + .getSubscription(subId); + assertEq(balance, 0); + assertEq(reqCount, 0); + assertEq(owner, s_subOwner); + assertEq(consumers.length, 1); + assertEq(consumers[0], address(s_vrfConsumerV2Plus)); + vm.stopPrank(); + } + + // cannot add a consumer to a nonexistent subscription + function test_AddConsumerToInvalidSub() public { + vm.startPrank(s_subOwner); + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + s_vrfCoordinatorV2_5Mock.addConsumer(1, address(s_vrfConsumerV2Plus)); + vm.stopPrank(); + } + + // cannot add more than the consumer maximum + function test_AddMaxConsumers() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + // Add 100 consumers + for (uint64 i = 101; i <= 200; ++i) { + s_vrfCoordinatorV2_5Mock.addConsumer(subId, address(bytes20(keccak256(abi.encodePacked(i))))); + } + // Adding 101th consumer should revert + vm.expectRevert(SubscriptionAPI.TooManyConsumers.selector); + s_vrfCoordinatorV2_5Mock.addConsumer(subId, address(s_vrfConsumerV2Plus)); + vm.stopPrank(); + } + + // can remove a consumer from a subscription + function test_RemoveConsumerFromSub() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + s_vrfCoordinatorV2_5Mock.addConsumer(subId, address(s_vrfConsumerV2Plus)); + + (, , , , address[] memory consumers) = s_vrfCoordinatorV2_5Mock.getSubscription(subId); + assertEq(consumers.length, 1); + assertEq(consumers[0], address(s_vrfConsumerV2Plus)); + + vm.expectEmit(true, false, false, true); + emit SubscriptionConsumerRemoved(subId, address(s_vrfConsumerV2Plus)); + s_vrfCoordinatorV2_5Mock.removeConsumer(subId, address(s_vrfConsumerV2Plus)); + + // Removing consumer again should revert with InvalidConsumer + vm.expectRevert( + abi.encodeWithSelector(SubscriptionAPI.InvalidConsumer.selector, subId, address(s_vrfConsumerV2Plus)) + ); + s_vrfCoordinatorV2_5Mock.removeConsumer(subId, address(s_vrfConsumerV2Plus)); + + vm.stopPrank(); + } + + // cannot remove a consumer from a nonexistent subscription + function test_RemoveConsumerFromInvalidSub() public { + vm.startPrank(s_subOwner); + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + s_vrfCoordinatorV2_5Mock.removeConsumer(1, address(s_vrfConsumerV2Plus)); + vm.stopPrank(); + } + + // cannot remove a consumer after it is already removed + function test_RemoveConsumerAgain() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + s_vrfCoordinatorV2_5Mock.addConsumer(subId, address(s_vrfConsumerV2Plus)); + + (, , , , address[] memory consumers) = s_vrfCoordinatorV2_5Mock.getSubscription(subId); + assertEq(consumers.length, 1); + assertEq(consumers[0], address(s_vrfConsumerV2Plus)); + + vm.expectEmit(true, false, false, true); + emit SubscriptionConsumerRemoved(subId, address(s_vrfConsumerV2Plus)); + s_vrfCoordinatorV2_5Mock.removeConsumer(subId, address(s_vrfConsumerV2Plus)); + + // Removing consumer again should revert with InvalidConsumer + vm.expectRevert( + abi.encodeWithSelector(SubscriptionAPI.InvalidConsumer.selector, subId, address(s_vrfConsumerV2Plus)) + ); + s_vrfCoordinatorV2_5Mock.removeConsumer(subId, address(s_vrfConsumerV2Plus)); + vm.stopPrank(); + } + + // can fund a subscription + function test_FundSubscription() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + vm.expectEmit(true, false, false, true); + emit SubscriptionFunded(subId, 0, twoLink); + s_vrfCoordinatorV2_5Mock.fundSubscription(subId, twoLink); + + (uint96 balance, , , , address[] memory consumers) = s_vrfCoordinatorV2_5Mock.getSubscription(subId); + assertEq(balance, twoLink); + assertEq(consumers.length, 0); + + assertEq(s_vrfCoordinatorV2_5Mock.s_totalBalance(), twoLink); + + vm.stopPrank(); + } + + // cannot fund a nonexistent subscription + function testFuzz_FundSubscription_RevertIfInvalidSubscription(uint256 subId) public { + vm.startPrank(s_subOwner); + + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + s_vrfCoordinatorV2_5Mock.fundSubscription(subId, twoLink); + + vm.stopPrank(); + } + + // can fund a subscription with native + function test_FundSubscriptionWithNative() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + vm.expectEmit(true, false, false, true); + emit SubscriptionFundedWithNative(subId, 0, oneNative); + s_vrfCoordinatorV2_5Mock.fundSubscriptionWithNative{value: oneNative}(subId); + + (, uint256 nativeBalance, , , address[] memory consumers) = s_vrfCoordinatorV2_5Mock.getSubscription(subId); + assertEq(nativeBalance, oneNative); + assertEq(consumers.length, 0); + + assertEq(s_vrfCoordinatorV2_5Mock.s_totalNativeBalance(), oneNative); + + vm.stopPrank(); + } + + // cannot fund a nonexistent subscription + function testFuzz_FundSubscriptionWithNative_RevertIfInvalidSubscription(uint256 subId) public { + vm.startPrank(s_subOwner); + + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + s_vrfCoordinatorV2_5Mock.fundSubscriptionWithNative{value: oneNative}(subId); + + vm.stopPrank(); + } + + // can cancel a subscription + function test_CancelSubscription_Link() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + s_vrfCoordinatorV2_5Mock.fundSubscription(subId, twoLink); + + uint256 totalBalance = s_vrfCoordinatorV2_5Mock.s_totalBalance(); + + vm.expectEmit(true, false, false, true); + emit SubscriptionCanceled(subId, s_subOwner, twoLink, 0); + s_vrfCoordinatorV2_5Mock.cancelSubscription(subId, s_subOwner); + + // check coordinator balance decreased + assertEq(s_vrfCoordinatorV2_5Mock.s_totalBalance(), totalBalance - twoLink); + + // sub owner balance did not increase as no actual token is involved + + // check subscription removed + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + s_vrfCoordinatorV2_5Mock.getSubscription(subId); + + vm.stopPrank(); + } + + // can cancel a subscription + function test_CancelSubscription_Native() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + s_vrfCoordinatorV2_5Mock.fundSubscriptionWithNative{value: oneNative}(subId); + + uint256 balance = address(s_subOwner).balance; + uint256 totalNativeBalance = s_vrfCoordinatorV2_5Mock.s_totalNativeBalance(); + + vm.expectEmit(true, false, false, true); + emit SubscriptionCanceled(subId, s_subOwner, 0, oneNative); + s_vrfCoordinatorV2_5Mock.cancelSubscription(subId, s_subOwner); + + // check coordinator balance decreased + assertEq(s_vrfCoordinatorV2_5Mock.s_totalNativeBalance(), totalNativeBalance - oneNative); + + // check sub owner balance increased + assertEq(address(s_subOwner).balance, balance + oneNative); + + // check subscription removed + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + s_vrfCoordinatorV2_5Mock.getSubscription(subId); + + vm.stopPrank(); + } + + // fails to fulfill without being a valid consumer + function testFuzz_RequestRandomWords_RevertIfInvalidConsumer(bool nativePayment) public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + s_vrfCoordinatorV2_5Mock.fundSubscription(subId, twoLink); + + vm.expectRevert(abi.encodeWithSelector(SubscriptionAPI.InvalidConsumer.selector, subId, address(s_subOwner))); + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: KEY_HASH, + subId: subId, + requestConfirmations: DEFAULT_REQUEST_CONFIRMATIONS, + callbackGasLimit: DEFAULT_CALLBACK_GAS_LIMIT, + numWords: DEFAULT_NUM_WORDS, + extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: nativePayment})) + }); + s_vrfCoordinatorV2_5Mock.requestRandomWords(req); + vm.stopPrank(); + } + + // fails to fulfill with insufficient funds + function testFuzz_RequestRandomWords_RevertIfInsufficientFunds(bool nativePayment) public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + address consumerAddr = address(s_vrfConsumerV2Plus); + s_vrfCoordinatorV2_5Mock.addConsumer(subId, address(s_vrfConsumerV2Plus)); + + vm.stopPrank(); + + vm.startPrank(consumerAddr); + + vm.expectEmit(true, false, false, true); + bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: nativePayment})); + emit RandomWordsRequested( + KEY_HASH, + 1, + 100, + subId, + DEFAULT_REQUEST_CONFIRMATIONS, + DEFAULT_CALLBACK_GAS_LIMIT, + DEFAULT_NUM_WORDS, + extraArgs, + address(s_subOwner) + ); + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: KEY_HASH, + subId: subId, + requestConfirmations: DEFAULT_REQUEST_CONFIRMATIONS, + callbackGasLimit: DEFAULT_CALLBACK_GAS_LIMIT, + numWords: DEFAULT_NUM_WORDS, + extraArgs: extraArgs + }); + uint256 reqId = s_vrfCoordinatorV2_5Mock.requestRandomWords(req); + + vm.expectRevert(SubscriptionAPI.InsufficientBalance.selector); + s_vrfCoordinatorV2_5Mock.fulfillRandomWords(reqId, consumerAddr); + + vm.stopPrank(); + } + + // can request and fulfill [ @skip-coverage ] + function test_RequestRandomWords_Link_HappyPath() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + s_vrfCoordinatorV2_5Mock.fundSubscription(subId, twoLink); + + address consumerAddr = address(s_vrfConsumerV2Plus); + s_vrfCoordinatorV2_5Mock.addConsumer(subId, consumerAddr); + + vm.expectEmit(true, false, false, true); + bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})); + emit RandomWordsRequested( + KEY_HASH, + 1, + 100, + subId, + DEFAULT_REQUEST_CONFIRMATIONS, + DEFAULT_CALLBACK_GAS_LIMIT, + DEFAULT_NUM_WORDS, + extraArgs, + address(s_subOwner) + ); + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: KEY_HASH, + subId: subId, + requestConfirmations: DEFAULT_REQUEST_CONFIRMATIONS, + callbackGasLimit: DEFAULT_CALLBACK_GAS_LIMIT, + numWords: DEFAULT_NUM_WORDS, + extraArgs: extraArgs + }); + uint256 reqId = s_vrfConsumerV2Plus.requestRandomness(req); + + vm.expectEmit(true, false, false, true); + emit RandomWordsFulfilled(reqId, 1, subId, 1432960000000000000, false, true, false); + s_vrfCoordinatorV2_5Mock.fulfillRandomWords(reqId, consumerAddr); + + vm.stopPrank(); + } + + // can request and fulfill [ @skip-coverage ] + function test_RequestRandomWords_Native_HappyPath() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + s_vrfCoordinatorV2_5Mock.fundSubscriptionWithNative{value: oneNative}(subId); + + address consumerAddr = address(s_vrfConsumerV2Plus); + s_vrfCoordinatorV2_5Mock.addConsumer(subId, consumerAddr); + + vm.expectEmit(true, false, false, true); + bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})); + emit RandomWordsRequested( + KEY_HASH, + 1, + 100, + subId, + DEFAULT_REQUEST_CONFIRMATIONS, + DEFAULT_CALLBACK_GAS_LIMIT, + DEFAULT_NUM_WORDS, + extraArgs, + address(s_subOwner) + ); + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: KEY_HASH, + subId: subId, + requestConfirmations: DEFAULT_REQUEST_CONFIRMATIONS, + callbackGasLimit: DEFAULT_CALLBACK_GAS_LIMIT, + numWords: DEFAULT_NUM_WORDS, + extraArgs: extraArgs + }); + uint256 reqId = s_vrfConsumerV2Plus.requestRandomness(req); + + vm.expectEmit(true, false, false, true); + emit RandomWordsFulfilled(reqId, 1, subId, 5731840000000000, true, true, false); + s_vrfCoordinatorV2_5Mock.fulfillRandomWords(reqId, consumerAddr); + + vm.stopPrank(); + } + + // Correctly allows for user override of fulfillRandomWords [ @skip-coverage ] + function testFuzz_RequestRandomWordsUserOverride(bool nativePayment) public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + uint96 expectedPayment; + if (nativePayment) { + expectedPayment = 5011440000000000; + s_vrfCoordinatorV2_5Mock.fundSubscriptionWithNative{value: oneNative}(subId); + } else { + expectedPayment = 1252860000000000000; + s_vrfCoordinatorV2_5Mock.fundSubscription(subId, twoLink); + } + + address consumerAddr = address(s_vrfConsumerV2Plus); + s_vrfCoordinatorV2_5Mock.addConsumer(subId, consumerAddr); + + bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: nativePayment})); + vm.expectEmit(true, false, false, true); + emit RandomWordsRequested( + KEY_HASH, + 1, + 100, + subId, + DEFAULT_REQUEST_CONFIRMATIONS, + DEFAULT_CALLBACK_GAS_LIMIT, + 2, + extraArgs, + address(s_subOwner) + ); + + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: KEY_HASH, + subId: subId, + requestConfirmations: DEFAULT_REQUEST_CONFIRMATIONS, + callbackGasLimit: DEFAULT_CALLBACK_GAS_LIMIT, + numWords: 2, + extraArgs: extraArgs + }); + uint256 reqId = s_vrfConsumerV2Plus.requestRandomness(req); + + vm.expectRevert(VRFCoordinatorV2_5Mock.InvalidRandomWords.selector); + uint256[] memory words1 = new uint256[](5); + words1[0] = 1; + words1[1] = 2; + words1[2] = 3; + words1[3] = 4; + words1[4] = 5; + s_vrfCoordinatorV2_5Mock.fulfillRandomWordsWithOverride(reqId, consumerAddr, uint256[](words1)); + + vm.expectEmit(true, false, false, true); + uint256[] memory words2 = new uint256[](2); + words1[0] = 2533; + words1[1] = 1768; + emit RandomWordsFulfilled(reqId, 1, subId, expectedPayment, nativePayment, true, false); + s_vrfCoordinatorV2_5Mock.fulfillRandomWordsWithOverride(reqId, consumerAddr, words2); + + vm.stopPrank(); + } +} diff --git a/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2Plus.sol b/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2Plus.sol new file mode 100644 index 00000000000..f0acade0bb6 --- /dev/null +++ b/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2Plus.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IVRFCoordinatorV2Plus, IVRFSubscriptionV2Plus} from "../dev/interfaces/IVRFCoordinatorV2Plus.sol"; +import {VRFV2PlusClient} from "../dev/libraries/VRFV2PlusClient.sol"; +import {VRFConsumerBaseV2Plus} from "../dev/VRFConsumerBaseV2Plus.sol"; +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; + +contract VRFConsumerV2Plus is VRFConsumerBaseV2Plus { + uint256[] public s_randomWords; + uint256 public s_requestId; + IVRFCoordinatorV2Plus internal COORDINATOR; + LinkTokenInterface internal LINKTOKEN; + uint256 public s_subId; + uint256 public s_gasAvailable; + + constructor(address vrfCoordinator, address link) VRFConsumerBaseV2Plus(vrfCoordinator) { + COORDINATOR = IVRFCoordinatorV2Plus(vrfCoordinator); + LINKTOKEN = LinkTokenInterface(link); + } + + function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal override { + require(requestId == s_requestId, "request ID is incorrect"); + + s_gasAvailable = gasleft(); + s_randomWords = randomWords; + } + + function createSubscriptionAndFund(uint96 amount) external { + if (s_subId == 0) { + s_subId = COORDINATOR.createSubscription(); + COORDINATOR.addConsumer(s_subId, address(this)); + } + // Approve the link transfer. + LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); + } + + function topUpSubscription(uint96 amount) external { + require(s_subId != 0, "sub not set"); + // Approve the link transfer. + LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); + } + + function updateSubscription(address[] memory consumers) external { + require(s_subId != 0, "subID not set"); + for (uint256 i = 0; i < consumers.length; i++) { + COORDINATOR.addConsumer(s_subId, consumers[i]); + } + } + + function requestRandomness(VRFV2PlusClient.RandomWordsRequest calldata req) external returns (uint256) { + s_requestId = COORDINATOR.requestRandomWords(req); + return s_requestId; + } +} From 03f0010ca213c34abe9f65a050feae7b9d8621c5 Mon Sep 17 00:00:00 2001 From: HenryNguyen5 <6404866+HenryNguyen5@users.noreply.github.com> Date: Thu, 2 May 2024 12:01:52 -0400 Subject: [PATCH 31/45] Add run attempt to run URL (#13063) --- tools/flakeytests/cmd/runner/main.go | 7 ++++++- tools/flakeytests/utils.go | 8 ++++---- tools/flakeytests/utils_test.go | 8 ++++---- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/tools/flakeytests/cmd/runner/main.go b/tools/flakeytests/cmd/runner/main.go index 2a1c5633577..0e1be5e7d38 100644 --- a/tools/flakeytests/cmd/runner/main.go +++ b/tools/flakeytests/cmd/runner/main.go @@ -33,6 +33,11 @@ func main() { ghRunID := flag.String("gh_run_id", "", "run id of the gh workflow") flag.Parse() + runAttempt := os.Getenv("GITHUB_RUN_ATTEMPT") + if runAttempt == "" { + log.Fatalf("GITHUB_RUN_ATTEMPT is required") + } + if *grafanaHost == "" { log.Fatal("Error re-running flakey tests: `grafana_host` is required") } @@ -62,7 +67,7 @@ func main() { readers = append(readers, r) } - meta := flakeytests.GetGithubMetadata(*ghRepo, *ghEventName, *ghSHA, *ghEventPath, *ghRunID) + meta := flakeytests.GetGithubMetadata(*ghRepo, *ghEventName, *ghSHA, *ghEventPath, *ghRunID, runAttempt) rep := flakeytests.NewLokiReporter(*grafanaHost, *grafanaAuth, *grafanaOrgID, *command, meta) r := flakeytests.NewRunner(readers, rep, numReruns) err := r.Run(ctx) diff --git a/tools/flakeytests/utils.go b/tools/flakeytests/utils.go index d2326c47262..96d6a02ded5 100644 --- a/tools/flakeytests/utils.go +++ b/tools/flakeytests/utils.go @@ -30,7 +30,7 @@ func DigString(mp map[string]interface{}, path []string) (string, error) { return vs, nil } -func getGithubMetadata(repo string, eventName string, sha string, e io.Reader, runID string) Context { +func getGithubMetadata(repo string, eventName string, sha string, e io.Reader, runID string, runAttempt string) Context { d, err := io.ReadAll(e) if err != nil { log.Fatal("Error reading gh event into string") @@ -42,7 +42,7 @@ func getGithubMetadata(repo string, eventName string, sha string, e io.Reader, r log.Fatalf("Error unmarshaling gh event at path") } - runURL := fmt.Sprintf("github.com/%s/actions/runs/%s", repo, runID) + runURL := fmt.Sprintf("github.com/%s/actions/runs/%s/attempts/%s", repo, runID, runAttempt) basicCtx := &Context{Repository: repo, CommitSHA: sha, Type: eventName, RunURL: runURL} switch eventName { case "pull_request": @@ -70,10 +70,10 @@ func getGithubMetadata(repo string, eventName string, sha string, e io.Reader, r } } -func GetGithubMetadata(repo string, eventName string, sha string, path string, runID string) Context { +func GetGithubMetadata(repo string, eventName string, sha string, path string, runID string, runAttempt string) Context { event, err := os.Open(path) if err != nil { log.Fatalf("Error reading gh event at path: %s", path) } - return getGithubMetadata(repo, eventName, sha, event, runID) + return getGithubMetadata(repo, eventName, sha, event, runID, runAttempt) } diff --git a/tools/flakeytests/utils_test.go b/tools/flakeytests/utils_test.go index 6ea912d11d4..d63ff041749 100644 --- a/tools/flakeytests/utils_test.go +++ b/tools/flakeytests/utils_test.go @@ -36,14 +36,14 @@ var prEventTemplate = ` ` func TestGetGithubMetadata(t *testing.T) { - repo, eventName, sha, event, runID := "chainlink", "merge_group", "a-sha", `{}`, "1234" - expectedRunURL := fmt.Sprintf("github.com/%s/actions/runs/%s", repo, runID) - ctx := getGithubMetadata(repo, eventName, sha, strings.NewReader(event), runID) + repo, eventName, sha, event, runID, runAttempt := "chainlink", "merge_group", "a-sha", `{}`, "1234", "1" + expectedRunURL := fmt.Sprintf("github.com/%s/actions/runs/%s/attempts/%s", repo, runID, runAttempt) + ctx := getGithubMetadata(repo, eventName, sha, strings.NewReader(event), runID, runAttempt) assert.Equal(t, Context{Repository: repo, CommitSHA: sha, Type: eventName, RunURL: expectedRunURL}, ctx) anotherSha, eventName, url := "another-sha", "pull_request", "a-url" event = fmt.Sprintf(prEventTemplate, anotherSha, url) sha = "302eb05d592132309b264e316f443f1ceb81b6c3" - ctx = getGithubMetadata(repo, eventName, sha, strings.NewReader(event), runID) + ctx = getGithubMetadata(repo, eventName, sha, strings.NewReader(event), runID, runAttempt) assert.Equal(t, Context{Repository: repo, CommitSHA: anotherSha, Type: eventName, PullRequestURL: url, RunURL: expectedRunURL}, ctx) } From 4c6f1341e0ceaad2603141f0a3f666bcf52fbc69 Mon Sep 17 00:00:00 2001 From: Tate Date: Thu, 2 May 2024 10:04:33 -0600 Subject: [PATCH 32/45] Fix CI-Scripts workflow to only run on pull_request (#13083) It was attempting to do this but also had push running which can mess up r --- .github/workflows/ci-scripts.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/ci-scripts.yml b/.github/workflows/ci-scripts.yml index 814c354cfe6..536973fc998 100644 --- a/.github/workflows/ci-scripts.yml +++ b/.github/workflows/ci-scripts.yml @@ -1,12 +1,11 @@ name: CI Scripts on: - push: + merge_group: pull_request: jobs: lint-scripts: - if: ${{ github.event_name == 'pull_request' }} runs-on: ubuntu-latest steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 @@ -23,7 +22,6 @@ jobs: gc-org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} test-scripts: - if: ${{ github.event_name == 'pull_request' }} runs-on: ubuntu-latest steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 From 1e23d736c53a17dbc3130ce52a80b6d168d06a41 Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Thu, 2 May 2024 12:55:10 -0400 Subject: [PATCH 33/45] Remove node6 for CRIB chart values (#13003) * Remove node6 for CRIB chart values * Use future helm chart and correct path to values-profiles override * Add back .gitignore * Update unnecessary trigger on ci-scripts owrkflow * Revert "Update unnecessary trigger on ci-scripts owrkflow" This reverts commit 7f618a15a9b42ff8cb9e55754141dbfed89edac2. --------- Co-authored-by: Gheorghe Strimtu Co-authored-by: Tate --- .github/scripts/crib/pr-comment-crib-env.js | 1 - crib/.gitignore | 3 +++ crib/devspace.yaml | 17 +++-------------- 3 files changed, 6 insertions(+), 15 deletions(-) create mode 100644 crib/.gitignore diff --git a/.github/scripts/crib/pr-comment-crib-env.js b/.github/scripts/crib/pr-comment-crib-env.js index d569587baff..cc36a9deb7b 100755 --- a/.github/scripts/crib/pr-comment-crib-env.js +++ b/.github/scripts/crib/pr-comment-crib-env.js @@ -11,7 +11,6 @@ function generateSubdomains(subdomainPrefix, prNumber) { "node3", "node4", "node5", - "node6", "geth-1337-http", "geth-1337-ws", "geth-2337-http", diff --git a/crib/.gitignore b/crib/.gitignore new file mode 100644 index 00000000000..9edd651d4db --- /dev/null +++ b/crib/.gitignore @@ -0,0 +1,3 @@ +values-profiles/* +!values-profiles/values-dev.yaml.example +!values-profiles/README.md diff --git a/crib/devspace.yaml b/crib/devspace.yaml index 213fe4c24c7..f22e710f943 100644 --- a/crib/devspace.yaml +++ b/crib/devspace.yaml @@ -74,7 +74,7 @@ images: docker push $image hooks: - command: ./scripts/check_env_vars.sh - events: [ "before:deploy:app" ] + events: ["before:deploy:app"] - wait: running: true terminatedWithCode: 0 @@ -100,7 +100,7 @@ deployments: releaseName: "app" chart: name: ${CHAINLINK_CLUSTER_HELM_CHART_URI} - version: 0.5.0 + version: 0.6.0 # for simplicity, we define all the values here # they can be defined the same way in values.yml # devspace merges these "values" with the "values.yaml" before deploy @@ -217,8 +217,6 @@ deployments: image: ${runtime.images.app} - name: node-5 image: ${runtime.images.app} - - name: node-6 - image: ${runtime.images.app} # each CL node have a dedicated PostgreSQL 11.15 # use StatefulSet by setting: @@ -348,15 +346,6 @@ deployments: name: app-node-5 port: number: 6688 - - host: ${DEVSPACE_NAMESPACE}-node6.${DEVSPACE_INGRESS_BASE_DOMAIN} - http: - paths: - - path: / - backend: - service: - name: app-node-6 - port: - number: 6688 - host: ${DEVSPACE_NAMESPACE}-geth-1337-http.${DEVSPACE_INGRESS_BASE_DOMAIN} http: paths: @@ -432,4 +421,4 @@ profiles: path: deployments.app.helm.values.chainlink.global.overridesToml - op: add path: deployments.app.helm.valuesFiles - value: ["../charts/chainlink-cluster/values-profiles/values-dev.yaml"] + value: ["./values-profiles/values-dev.yaml"] From fbbadfb6a1ef746aff9a98178e6186e12f4a4f54 Mon Sep 17 00:00:00 2001 From: frank zhu Date: Thu, 2 May 2024 12:37:28 -0700 Subject: [PATCH 34/45] fix: ci-core print-races to slack conditionals (#13086) --- .github/workflows/ci-core.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml index 1d7b58820b0..a3ea68380f9 100644 --- a/.github/workflows/ci-core.yml +++ b/.github/workflows/ci-core.yml @@ -170,7 +170,7 @@ jobs: env: OUTPUT_FILE: ./output.txt USE_TEE: false - CL_DATABASE_URL: ${{ env.DB_URL }} + CL_DATABASE_URL: ${{ env.DB_URL }} run: ./tools/bin/${{ matrix.type.cmd }} ./... - name: Print Filtered Test Results if: ${{ failure() && matrix.type.cmd == 'go_core_tests' && needs.filter.outputs.changes == 'true' }} @@ -203,7 +203,7 @@ jobs: ./coverage.txt ./postgres_logs.txt - name: Notify Slack - if: ${{ failure() && steps.print-races.outputs.post_to_slack == 'true' && matrix.type.cmd == 'go_core_race_tests' && (github.event_name == 'merge_group' || github.event.branch == 'develop') && needs.filter.outputs.changes == 'true' }} + if: ${{ failure() && steps.print-races.outputs.post_to_slack == 'true' && matrix.type.cmd == 'go_core_race_tests' && (github.event_name == 'merge_group' || github.base_ref == 'develop') && needs.filter.outputs.changes == 'true' }} uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 env: SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} From 5633b51ba1516598d189e61908ea3c6e89da5f01 Mon Sep 17 00:00:00 2001 From: Lei Date: Thu, 2 May 2024 13:49:10 -0700 Subject: [PATCH 35/45] add coverage for registrar and registry (#12988) * add coverage for registry and registrar * address comments --- .../dev/test/AutomationRegistrar2_3.t.sol | 165 ++++++++++++++++++ .../dev/test/AutomationRegistry2_3.t.sol | 62 ++++++- .../v0.8/automation/dev/test/BaseTest.t.sol | 4 + 3 files changed, 229 insertions(+), 2 deletions(-) diff --git a/contracts/src/v0.8/automation/dev/test/AutomationRegistrar2_3.t.sol b/contracts/src/v0.8/automation/dev/test/AutomationRegistrar2_3.t.sol index 76b808d1f05..2b55651dbe8 100644 --- a/contracts/src/v0.8/automation/dev/test/AutomationRegistrar2_3.t.sol +++ b/contracts/src/v0.8/automation/dev/test/AutomationRegistrar2_3.t.sol @@ -16,11 +16,97 @@ contract SetUp is BaseTest { function setUp() public override { super.setUp(); + vm.startPrank(OWNER); (registry, registrar) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); vm.stopPrank(); // reset identity at the start of each test } } +contract CancelUpkeep is SetUp { + function testUSDToken_happy() external { + vm.startPrank(UPKEEP_ADMIN); + + uint96 amount = uint96(registrar.getMinimumRegistrationAmount(usdToken18)); + usdToken18.approve(address(registrar), amount); + + AutomationRegistrar2_3.RegistrationParams memory registrationParams = AutomationRegistrar2_3.RegistrationParams({ + upkeepContract: address(TARGET1), + amount: amount, + adminAddress: UPKEEP_ADMIN, + gasLimit: 10_000, + triggerType: 0, + billingToken: usdToken18, + name: "foobar", + encryptedEmail: "", + checkData: bytes("check data"), + triggerConfig: "", + offchainConfig: "" + }); + + // default is auto approve off + registrar.registerUpkeep(registrationParams); + + assertEq(usdToken18.balanceOf(address(registrar)), amount); + assertEq(registry.getNumUpkeeps(), 0); + + uint256 startRegistrarBalance = usdToken18.balanceOf(address(registrar)); + uint256 startUpkeepAdminBalance = usdToken18.balanceOf(UPKEEP_ADMIN); + + // cancel the upkeep + vm.startPrank(OWNER); + bytes32 hash = keccak256(abi.encode(registrationParams)); + registrar.cancel(hash); + + uint256 endRegistrarBalance = usdToken18.balanceOf(address(registrar)); + uint256 endUpkeepAdminBalance = usdToken18.balanceOf(UPKEEP_ADMIN); + + assertEq(startRegistrarBalance - amount, endRegistrarBalance); + assertEq(startUpkeepAdminBalance + amount, endUpkeepAdminBalance); + } +} + +contract ApproveUpkeep is SetUp { + function testUSDToken_happy() external { + vm.startPrank(UPKEEP_ADMIN); + + uint96 amount = uint96(registrar.getMinimumRegistrationAmount(usdToken18)); + usdToken18.approve(address(registrar), amount); + + AutomationRegistrar2_3.RegistrationParams memory registrationParams = AutomationRegistrar2_3.RegistrationParams({ + upkeepContract: address(TARGET1), + amount: amount, + adminAddress: UPKEEP_ADMIN, + gasLimit: 10_000, + triggerType: 0, + billingToken: usdToken18, + name: "foobar", + encryptedEmail: "", + checkData: bytes("check data"), + triggerConfig: "", + offchainConfig: "" + }); + + // default is auto approve off + registrar.registerUpkeep(registrationParams); + + assertEq(usdToken18.balanceOf(address(registrar)), amount); + assertEq(registry.getNumUpkeeps(), 0); + + uint256 startRegistrarBalance = usdToken18.balanceOf(address(registrar)); + uint256 startRegistryBalance = usdToken18.balanceOf(address(registry)); + + // approve the upkeep + vm.startPrank(OWNER); + registrar.approve(registrationParams); + + uint256 endRegistrarBalance = usdToken18.balanceOf(address(registrar)); + uint256 endRegistryBalance = usdToken18.balanceOf(address(registry)); + + assertEq(startRegistrarBalance - amount, endRegistrarBalance); + assertEq(startRegistryBalance + amount, endRegistryBalance); + } +} + contract RegisterUpkeep is SetUp { function testLink_autoApproveOff_happy() external { vm.startPrank(UPKEEP_ADMIN); @@ -75,6 +161,7 @@ contract RegisterUpkeep is SetUp { } function testLink_autoApproveOn_happy() external { + vm.startPrank(OWNER); registrar.setTriggerConfig(0, AutomationRegistrar2_3.AutoApproveType.ENABLED_ALL, 1000); vm.startPrank(UPKEEP_ADMIN); @@ -103,6 +190,7 @@ contract RegisterUpkeep is SetUp { } function testUSDToken_autoApproveOn_happy() external { + vm.startPrank(OWNER); registrar.setTriggerConfig(0, AutomationRegistrar2_3.AutoApproveType.ENABLED_ALL, 1000); vm.startPrank(UPKEEP_ADMIN); @@ -131,6 +219,7 @@ contract RegisterUpkeep is SetUp { } function testNative_autoApproveOn_happy() external { + vm.startPrank(OWNER); registrar.setTriggerConfig(0, AutomationRegistrar2_3.AutoApproveType.ENABLED_ALL, 1000); vm.startPrank(UPKEEP_ADMIN); @@ -241,4 +330,80 @@ contract RegisterUpkeep is SetUp { vm.expectRevert(AutomationRegistrar2_3.DuplicateEntry.selector); registrar.registerUpkeep(params); } + + function test_revertOnInsufficientPayment() external { + vm.startPrank(UPKEEP_ADMIN); + + // slightly less than the minimum amount + uint96 amount = uint96(registrar.getMinimumRegistrationAmount(IERC20(address(linkToken))) - 1); + linkToken.approve(address(registrar), amount); + + AutomationRegistrar2_3.RegistrationParams memory params = AutomationRegistrar2_3.RegistrationParams({ + upkeepContract: address(TARGET1), + amount: amount, + adminAddress: UPKEEP_ADMIN, + gasLimit: 10_000, + triggerType: 0, + billingToken: IERC20(address(linkToken)), + name: "foobar", + encryptedEmail: "", + checkData: bytes("check data"), + triggerConfig: "", + offchainConfig: "" + }); + + // attempt to register but revert bc of insufficient payment + vm.expectRevert(AutomationRegistrar2_3.InsufficientPayment.selector); + registrar.registerUpkeep(params); + } + + function test_revertOnInvalidAdminAddress() external { + vm.startPrank(UPKEEP_ADMIN); + + uint96 amount = uint96(registrar.getMinimumRegistrationAmount(IERC20(address(linkToken)))); + linkToken.approve(address(registrar), amount); + + AutomationRegistrar2_3.RegistrationParams memory params = AutomationRegistrar2_3.RegistrationParams({ + upkeepContract: address(TARGET1), + amount: amount, + adminAddress: ZERO_ADDRESS, // zero address is invalid + gasLimit: 10_000, + triggerType: 0, + billingToken: IERC20(address(linkToken)), + name: "foobar", + encryptedEmail: "", + checkData: bytes("check data"), + triggerConfig: "", + offchainConfig: "" + }); + + // attempt to register but revert bc of invalid admin address + vm.expectRevert(AutomationRegistrar2_3.InvalidAdminAddress.selector); + registrar.registerUpkeep(params); + } + + function test_revertOnInvalidBillingToken() external { + vm.startPrank(UPKEEP_ADMIN); + + uint96 amount = 1; + usdToken18_2.approve(address(registrar), amount); + + AutomationRegistrar2_3.RegistrationParams memory params = AutomationRegistrar2_3.RegistrationParams({ + upkeepContract: address(TARGET1), + amount: amount, + adminAddress: UPKEEP_ADMIN, + gasLimit: 10_000, + triggerType: 0, + billingToken: IERC20(address(usdToken18_2)), // unsupported billing token + name: "foobar", + encryptedEmail: "", + checkData: bytes("check data"), + triggerConfig: "", + offchainConfig: "" + }); + + // attempt to register but revert bc of invalid admin address + vm.expectRevert(AutomationRegistrar2_3.InvalidBillingToken.selector); + registrar.registerUpkeep(params); + } } diff --git a/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol b/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol index 03138696436..6da98e16fe5 100644 --- a/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol +++ b/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol @@ -136,11 +136,69 @@ contract CheckUpkeep is SetUp { } } +contract WithdrawFunds is SetUp { + event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); + + function test_RevertsWhen_CalledByNonAdmin() external { + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + vm.prank(STRANGER); + registry.withdrawFunds(linkUpkeepID, STRANGER); + } + + function test_RevertsWhen_InvalidRecipient() external { + vm.expectRevert(Registry.InvalidRecipient.selector); + vm.prank(UPKEEP_ADMIN); + registry.withdrawFunds(linkUpkeepID, ZERO_ADDRESS); + } + + function test_RevertsWhen_UpkeepNotCanceled() external { + vm.expectRevert(Registry.UpkeepNotCanceled.selector); + vm.prank(UPKEEP_ADMIN); + registry.withdrawFunds(linkUpkeepID, UPKEEP_ADMIN); + } + + function test_Happy_Link() external { + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + vm.roll(100 + block.number); + + uint256 startUpkeepAdminBalance = linkToken.balanceOf(UPKEEP_ADMIN); + uint256 startLinkReserveAmountBalance = registry.getReserveAmount(address(linkToken)); + + uint256 upkeepBalance = registry.getBalance(linkUpkeepID); + vm.expectEmit(); + emit FundsWithdrawn(linkUpkeepID, upkeepBalance, address(UPKEEP_ADMIN)); + registry.withdrawFunds(linkUpkeepID, UPKEEP_ADMIN); + + assertEq(registry.getBalance(linkUpkeepID), 0); + assertEq(linkToken.balanceOf(UPKEEP_ADMIN), startUpkeepAdminBalance + upkeepBalance); + assertEq(registry.getReserveAmount(address(linkToken)), startLinkReserveAmountBalance - upkeepBalance); + } + + function test_Happy_USDToken() external { + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(usdUpkeepID6); + vm.roll(100 + block.number); + + uint256 startUpkeepAdminBalance = usdToken6.balanceOf(UPKEEP_ADMIN); + uint256 startUSDToken6ReserveAmountBalance = registry.getReserveAmount(address(usdToken6)); + + uint256 upkeepBalance = registry.getBalance(usdUpkeepID6); + vm.expectEmit(); + emit FundsWithdrawn(usdUpkeepID6, upkeepBalance, address(UPKEEP_ADMIN)); + registry.withdrawFunds(usdUpkeepID6, UPKEEP_ADMIN); + + assertEq(registry.getBalance(usdUpkeepID6), 0); + assertEq(usdToken6.balanceOf(UPKEEP_ADMIN), startUpkeepAdminBalance + upkeepBalance); + assertEq(registry.getReserveAmount(address(usdToken6)), startUSDToken6ReserveAmountBalance - upkeepBalance); + } +} + contract AddFunds is SetUp { event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); // when msg.value is 0, it uses the ERC20 payment path - function testNative_msgValue0() external { + function test_HappyWhen_NativeUpkeep_WithMsgValue0() external { vm.startPrank(OWNER); uint256 startRegistryBalance = registry.getBalance(nativeUpkeepID); uint256 startTokenBalance = registry.getBalance(nativeUpkeepID); @@ -150,7 +208,7 @@ contract AddFunds is SetUp { } // when msg.value is not 0, it uses the native payment path - function testNative_msgValueNot0() external { + function test_HappyWhen_NativeUpkeep_WithMsgValueNot0() external { uint256 startRegistryBalance = registry.getBalance(nativeUpkeepID); uint256 startTokenBalance = registry.getBalance(nativeUpkeepID); registry.addFunds{value: 1}(nativeUpkeepID, 1000); // parameter amount should be ignored diff --git a/contracts/src/v0.8/automation/dev/test/BaseTest.t.sol b/contracts/src/v0.8/automation/dev/test/BaseTest.t.sol index 5ae9a29fc15..bba195b83e6 100644 --- a/contracts/src/v0.8/automation/dev/test/BaseTest.t.sol +++ b/contracts/src/v0.8/automation/dev/test/BaseTest.t.sol @@ -43,6 +43,7 @@ contract BaseTest is Test { LinkToken internal linkToken; ERC20Mock6Decimals internal usdToken6; ERC20Mock internal usdToken18; + ERC20Mock internal usdToken18_2; WETH9 internal weth; MockV3Aggregator internal LINK_USD_FEED; MockV3Aggregator internal NATIVE_USD_FEED; @@ -76,6 +77,7 @@ contract BaseTest is Test { linkToken = new LinkToken(); linkToken.grantMintRole(OWNER); usdToken18 = new ERC20Mock("MOCK_ERC20_18Decimals", "MOCK_ERC20_18Decimals", OWNER, 0); + usdToken18_2 = new ERC20Mock("Second_MOCK_ERC20_18Decimals", "Second_MOCK_ERC20_18Decimals", OWNER, 0); usdToken6 = new ERC20Mock6Decimals("MOCK_ERC20_6Decimals", "MOCK_ERC20_6Decimals", OWNER, 0); weth = new WETH9(); @@ -128,6 +130,8 @@ contract BaseTest is Test { usdToken18.mint(FINANCE_ADMIN, 1000e18); usdToken18.mint(STRANGER, 1000e18); + usdToken18_2.mint(UPKEEP_ADMIN, 1000e18); + usdToken6.mint(OWNER, 1000e6); usdToken6.mint(UPKEEP_ADMIN, 1000e6); usdToken6.mint(FINANCE_ADMIN, 1000e6); From 4e62b15d7ed98cb28ed08238f985b640a5892b37 Mon Sep 17 00:00:00 2001 From: frank zhu Date: Thu, 2 May 2024 13:56:40 -0700 Subject: [PATCH 36/45] exclude build-image gha if just changing changelog (#13065) * exclude build-image gha if just changing changelog * fix --- .github/workflows/build-publish-pr.yml | 2 +- .github/workflows/build.yml | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-publish-pr.yml b/.github/workflows/build-publish-pr.yml index a70f1227cc9..0737b742dc8 100644 --- a/.github/workflows/build-publish-pr.yml +++ b/.github/workflows/build-publish-pr.yml @@ -11,7 +11,7 @@ on: jobs: build-publish-untrusted: - if: ${{ ! startsWith(github.ref_name, 'release/') }} + if: ${{ ! startsWith(github.ref_name, 'release/') || (! startsWith(github.head_ref, 'release/') && ! startsWith(github.ref_name, 'chore/'))}} runs-on: ubuntu-20.04 environment: sdlc permissions: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 193a7a5d671..45193f6dc35 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,17 +6,39 @@ on: jobs: build-chainlink: runs-on: ubuntu-20.04 + if: ${{ ! startsWith(github.head_ref, 'release/') && ! startsWith(github.ref_name, 'chore/') }} steps: - name: Checkout repository uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + id: change + with: + predicate-quantifier: every + filters: | + changelog-only: + - 'CHANGELOG.md' + - '!common/**' + - '!contracts/**' + - '!core/**' + - '!crib/**' + - '!dashboard-lib/**' + - '!fuzz/**' + - '!integration-tests/**' + - '!internal/**' + - '!operator_ui/**' + - '!plugins/**' + - '!tools/**' + - name: Build chainlink image + if: ${{ steps.change.outputs.changelog-only == 'false' }} uses: ./.github/actions/build-sign-publish-chainlink with: dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }} dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }} publish: false sign-images: false + - name: Collect Metrics if: always() id: collect-gha-metrics From 53f26b216583cbf3f84608920fd1840574672ab1 Mon Sep 17 00:00:00 2001 From: HenryNguyen5 <6404866+HenryNguyen5@users.noreply.github.com> Date: Thu, 2 May 2024 23:36:09 -0400 Subject: [PATCH 37/45] Skip multi-node.txtar test due to high flake rate (#13090) --- testdata/scripts/metrics/multi-node.txtar | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/testdata/scripts/metrics/multi-node.txtar b/testdata/scripts/metrics/multi-node.txtar index c3928160443..0d43018c564 100644 --- a/testdata/scripts/metrics/multi-node.txtar +++ b/testdata/scripts/metrics/multi-node.txtar @@ -1,3 +1,4 @@ +skip 'High Flake Rate' # Check that metrics specified in the expected_metrics are present in /metrics response # start node exec sh -c 'eval "echo \"$(cat config.toml.tmpl)\" > config.toml"' @@ -75,4 +76,4 @@ multi_node_states{chainId="68472",network="EVM",state="InvalidChainID"} multi_node_states{chainId="68472",network="EVM",state="OutOfSync"} multi_node_states{chainId="68472",network="EVM",state="Undialed"} multi_node_states{chainId="68472",network="EVM",state="Unreachable"} -multi_node_states{chainId="68472",network="EVM",state="Unusable"} \ No newline at end of file +multi_node_states{chainId="68472",network="EVM",state="Unusable"} From d79bdf16c5129cf7bc7cc5114f92eb07fd3fbf02 Mon Sep 17 00:00:00 2001 From: Austin Born Date: Fri, 3 May 2024 08:32:28 -0700 Subject: [PATCH 38/45] Add gethwrappers for Operator Forwarder contracts (#13084) * Add gethwrappers for operatorforwarder * Changeset * Update .changeset/ninety-students-return.md * make generate --- .changeset/ninety-students-return.md | 5 + core/gethwrappers/go_generate.go | 3 + .../authorized_forwarder.go | 983 ++++++++++ .../authorized_receiver.go | 363 ++++ .../link_token_receiver.go | 197 ++ .../generated/operator/operator.go | 1731 +++++++++++++++++ .../operator_factory/operator_factory.go | 632 ++++++ ...rapper-dependency-versions-do-not-edit.txt | 6 + .../operatorforwarder/go_generate.go | 10 + 9 files changed, 3930 insertions(+) create mode 100644 .changeset/ninety-students-return.md create mode 100644 core/gethwrappers/operatorforwarder/generated/authorized_forwarder/authorized_forwarder.go create mode 100644 core/gethwrappers/operatorforwarder/generated/authorized_receiver/authorized_receiver.go create mode 100644 core/gethwrappers/operatorforwarder/generated/link_token_receiver/link_token_receiver.go create mode 100644 core/gethwrappers/operatorforwarder/generated/operator/operator.go create mode 100644 core/gethwrappers/operatorforwarder/generated/operator_factory/operator_factory.go create mode 100644 core/gethwrappers/operatorforwarder/generation/generated-wrapper-dependency-versions-do-not-edit.txt create mode 100644 core/gethwrappers/operatorforwarder/go_generate.go diff --git a/.changeset/ninety-students-return.md b/.changeset/ninety-students-return.md new file mode 100644 index 00000000000..d00737e7f24 --- /dev/null +++ b/.changeset/ninety-students-return.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#updated Add gethwrappers for operatorforwarder contracts diff --git a/core/gethwrappers/go_generate.go b/core/gethwrappers/go_generate.go index e31f7feb833..c5a55b18a05 100644 --- a/core/gethwrappers/go_generate.go +++ b/core/gethwrappers/go_generate.go @@ -155,6 +155,9 @@ package gethwrappers // Mercury //go:generate go generate ./llo-feeds +// Operator Forwarder +//go:generate go generate ./operatorforwarder + // Shared //go:generate go generate ./shared diff --git a/core/gethwrappers/operatorforwarder/generated/authorized_forwarder/authorized_forwarder.go b/core/gethwrappers/operatorforwarder/generated/authorized_forwarder/authorized_forwarder.go new file mode 100644 index 00000000000..03643c9154b --- /dev/null +++ b/core/gethwrappers/operatorforwarder/generated/authorized_forwarder/authorized_forwarder.go @@ -0,0 +1,983 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package authorized_forwarder + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +var AuthorizedForwarderMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"link\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"changedBy\",\"type\":\"address\"}],\"name\":\"AuthorizedSendersChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"OwnershipTransferRequestedWithMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"forward\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAuthorizedSenders\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"isAuthorizedSender\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"linkToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tos\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"datas\",\"type\":\"bytes[]\"}],\"name\":\"multiForward\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"ownerForward\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"setAuthorizedSenders\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"transferOwnershipWithMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b50604051620016993803806200169983398101604081905262000034916200029d565b82826001600160a01b038216620000925760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c557620000c58162000199565b50506001600160a01b0384166200012b5760405162461bcd60e51b815260206004820152602360248201527f4c696e6b20746f6b656e2063616e6e6f742062652061207a65726f206164647260448201526265737360e81b606482015260840162000089565b6001600160a01b038085166080528216156200018f57816001600160a01b0316836001600160a01b03167f4e1e878dc28d5f040db5969163ff1acd75c44c3f655da2dde9c70bbd8e56dc7e836040516200018691906200038e565b60405180910390a35b50505050620003c3565b336001600160a01b03821603620001f35760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000089565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b03811681146200025c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620002945781810151838201526020016200027a565b50506000910152565b60008060008060808587031215620002b457600080fd5b620002bf8562000244565b9350620002cf6020860162000244565b9250620002df6040860162000244565b60608601519092506001600160401b0380821115620002fd57600080fd5b818701915087601f8301126200031257600080fd5b81518181111562000327576200032762000261565b604051601f8201601f19908116603f0116810190838211818310171562000352576200035262000261565b816040528281528a60208487010111156200036c57600080fd5b6200037f83602083016020880162000277565b979a9699509497505050505050565b6020815260008251806020840152620003af81604085016020870162000277565b601f01601f19169190910160400192915050565b6080516112ac620003ed6000396000818161016d0152818161037501526105d301526112ac6000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c806379ba509711610081578063ee56997b1161005b578063ee56997b14610200578063f2fde38b14610213578063fa00763a1461022657600080fd5b806379ba5097146101c75780638da5cb5b146101cf578063b64fa9e6146101ed57600080fd5b80634d3e2323116100b25780634d3e23231461015557806357970e93146101685780636fadcf72146101b457600080fd5b8063033f49f7146100d9578063181f5a77146100ee5780632408afaa14610140575b600080fd5b6100ec6100e7366004610e72565b61026f565b005b61012a6040518060400160405280601981526020017f417574686f72697a6564466f7277617264657220312e312e300000000000000081525081565b6040516101379190610ef5565b60405180910390f35b610148610287565b6040516101379190610f61565b6100ec610163366004610e72565b6102f6565b61018f7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610137565b6100ec6101c2366004610e72565b61036b565b6100ec61042d565b60005473ffffffffffffffffffffffffffffffffffffffff1661018f565b6100ec6101fb366004611007565b61052a565b6100ec61020e366004611073565b6106cb565b6100ec6102213660046110b5565b6109dc565b61025f6102343660046110b5565b73ffffffffffffffffffffffffffffffffffffffff1660009081526002602052604090205460ff1690565b6040519015158152602001610137565b6102776109f0565b610282838383610a73565b505050565b606060038054806020026020016040519081016040528092919081815260200182805480156102ec57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116102c1575b5050505050905090565b6102ff836109dc565b8273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f4e1e878dc28d5f040db5969163ff1acd75c44c3f655da2dde9c70bbd8e56dc7e848460405161035e9291906110d7565b60405180910390a3505050565b610373610c00565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610277576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43616e6e6f7420666f727761726420746f204c696e6b20746f6b656e0000000060448201526064015b60405180910390fd5b60015473ffffffffffffffffffffffffffffffffffffffff1633146104ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610424565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610532610c00565b82811461059b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f417272617973206d7573742068617665207468652073616d65206c656e6774686044820152606401610424565b60005b838110156106c45760008585838181106105ba576105ba611124565b90506020020160208101906105cf91906110b5565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610686576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43616e6e6f7420666f727761726420746f204c696e6b20746f6b656e000000006044820152606401610424565b6106b38185858581811061069c5761069c611124565b90506020028101906106ae9190611153565b610a73565b506106bd816111b8565b905061059e565b5050505050565b6106d3610c79565b610739576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f742073657420617574686f72697a65642073656e646572730000006044820152606401610424565b806107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4d7573742068617665206174206c6561737420312073656e64657200000000006044820152606401610424565b60035460005b8181101561083657600060026000600384815481106107c7576107c7611124565b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905561082f816111b8565b90506107a6565b5060005b8281101561098e576002600085858481811061085857610858611124565b905060200201602081019061086d91906110b5565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000205460ff16156108fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4d757374206e6f742068617665206475706c69636174652073656e64657273006044820152606401610424565b60016002600086868581811061091657610916611124565b905060200201602081019061092b91906110b5565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055610987816111b8565b905061083a565b5061099b60038484610dac565b507ff263cfb3e4298332e776194610cf9fdc09ccb3ada8b9aa39764d882e11fbf0a08383336040516109cf93929190611217565b60405180910390a1505050565b6109e46109f0565b6109ed81610cb7565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610424565b565b73ffffffffffffffffffffffffffffffffffffffff83163b610af1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d75737420666f727761726420746f206120636f6e74726163740000000000006044820152606401610424565b6000808473ffffffffffffffffffffffffffffffffffffffff168484604051610b1b92919061128f565b6000604051808303816000865af19150503d8060008114610b58576040519150601f19603f3d011682016040523d82523d6000602084013e610b5d565b606091505b5091509150816106c4578051600003610bf8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f466f727761726465642063616c6c20726576657274656420776974686f75742060448201527f726561736f6e00000000000000000000000000000000000000000000000000006064820152608401610424565b805181602001fd5b3360009081526002602052604090205460ff16610a71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f7420617574686f72697a65642073656e64657200000000000000000000006044820152606401610424565b600033610c9b60005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b3373ffffffffffffffffffffffffffffffffffffffff821603610d36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610424565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b828054828255906000526020600020908101928215610e24579160200282015b82811115610e245781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff843516178255602090920191600190910190610dcc565b50610e30929150610e34565b5090565b5b80821115610e305760008155600101610e35565b803573ffffffffffffffffffffffffffffffffffffffff81168114610e6d57600080fd5b919050565b600080600060408486031215610e8757600080fd5b610e9084610e49565b9250602084013567ffffffffffffffff80821115610ead57600080fd5b818601915086601f830112610ec157600080fd5b813581811115610ed057600080fd5b876020828501011115610ee257600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b81811015610f2257858101830151858201604001528201610f06565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6020808252825182820181905260009190848201906040850190845b81811015610faf57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101610f7d565b50909695505050505050565b60008083601f840112610fcd57600080fd5b50813567ffffffffffffffff811115610fe557600080fd5b6020830191508360208260051b850101111561100057600080fd5b9250929050565b6000806000806040858703121561101d57600080fd5b843567ffffffffffffffff8082111561103557600080fd5b61104188838901610fbb565b9096509450602087013591508082111561105a57600080fd5b5061106787828801610fbb565b95989497509550505050565b6000806020838503121561108657600080fd5b823567ffffffffffffffff81111561109d57600080fd5b6110a985828601610fbb565b90969095509350505050565b6000602082840312156110c757600080fd5b6110d082610e49565b9392505050565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261118857600080fd5b83018035915067ffffffffffffffff8211156111a357600080fd5b60200191503681900382131561100057600080fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611210577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b6040808252810183905260008460608301825b868110156112655773ffffffffffffffffffffffffffffffffffffffff61125084610e49565b1682526020928301929091019060010161122a565b50809250505073ffffffffffffffffffffffffffffffffffffffff83166020830152949350505050565b818382376000910190815291905056fea164736f6c6343000813000a", +} + +var AuthorizedForwarderABI = AuthorizedForwarderMetaData.ABI + +var AuthorizedForwarderBin = AuthorizedForwarderMetaData.Bin + +func DeployAuthorizedForwarder(auth *bind.TransactOpts, backend bind.ContractBackend, link common.Address, owner common.Address, recipient common.Address, message []byte) (common.Address, *types.Transaction, *AuthorizedForwarder, error) { + parsed, err := AuthorizedForwarderMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(AuthorizedForwarderBin), backend, link, owner, recipient, message) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &AuthorizedForwarder{address: address, abi: *parsed, AuthorizedForwarderCaller: AuthorizedForwarderCaller{contract: contract}, AuthorizedForwarderTransactor: AuthorizedForwarderTransactor{contract: contract}, AuthorizedForwarderFilterer: AuthorizedForwarderFilterer{contract: contract}}, nil +} + +type AuthorizedForwarder struct { + address common.Address + abi abi.ABI + AuthorizedForwarderCaller + AuthorizedForwarderTransactor + AuthorizedForwarderFilterer +} + +type AuthorizedForwarderCaller struct { + contract *bind.BoundContract +} + +type AuthorizedForwarderTransactor struct { + contract *bind.BoundContract +} + +type AuthorizedForwarderFilterer struct { + contract *bind.BoundContract +} + +type AuthorizedForwarderSession struct { + Contract *AuthorizedForwarder + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type AuthorizedForwarderCallerSession struct { + Contract *AuthorizedForwarderCaller + CallOpts bind.CallOpts +} + +type AuthorizedForwarderTransactorSession struct { + Contract *AuthorizedForwarderTransactor + TransactOpts bind.TransactOpts +} + +type AuthorizedForwarderRaw struct { + Contract *AuthorizedForwarder +} + +type AuthorizedForwarderCallerRaw struct { + Contract *AuthorizedForwarderCaller +} + +type AuthorizedForwarderTransactorRaw struct { + Contract *AuthorizedForwarderTransactor +} + +func NewAuthorizedForwarder(address common.Address, backend bind.ContractBackend) (*AuthorizedForwarder, error) { + abi, err := abi.JSON(strings.NewReader(AuthorizedForwarderABI)) + if err != nil { + return nil, err + } + contract, err := bindAuthorizedForwarder(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &AuthorizedForwarder{address: address, abi: abi, AuthorizedForwarderCaller: AuthorizedForwarderCaller{contract: contract}, AuthorizedForwarderTransactor: AuthorizedForwarderTransactor{contract: contract}, AuthorizedForwarderFilterer: AuthorizedForwarderFilterer{contract: contract}}, nil +} + +func NewAuthorizedForwarderCaller(address common.Address, caller bind.ContractCaller) (*AuthorizedForwarderCaller, error) { + contract, err := bindAuthorizedForwarder(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &AuthorizedForwarderCaller{contract: contract}, nil +} + +func NewAuthorizedForwarderTransactor(address common.Address, transactor bind.ContractTransactor) (*AuthorizedForwarderTransactor, error) { + contract, err := bindAuthorizedForwarder(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &AuthorizedForwarderTransactor{contract: contract}, nil +} + +func NewAuthorizedForwarderFilterer(address common.Address, filterer bind.ContractFilterer) (*AuthorizedForwarderFilterer, error) { + contract, err := bindAuthorizedForwarder(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &AuthorizedForwarderFilterer{contract: contract}, nil +} + +func bindAuthorizedForwarder(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := AuthorizedForwarderMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_AuthorizedForwarder *AuthorizedForwarderRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AuthorizedForwarder.Contract.AuthorizedForwarderCaller.contract.Call(opts, result, method, params...) +} + +func (_AuthorizedForwarder *AuthorizedForwarderRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.AuthorizedForwarderTransactor.contract.Transfer(opts) +} + +func (_AuthorizedForwarder *AuthorizedForwarderRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.AuthorizedForwarderTransactor.contract.Transact(opts, method, params...) +} + +func (_AuthorizedForwarder *AuthorizedForwarderCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AuthorizedForwarder.Contract.contract.Call(opts, result, method, params...) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.contract.Transfer(opts) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.contract.Transact(opts, method, params...) +} + +func (_AuthorizedForwarder *AuthorizedForwarderCaller) GetAuthorizedSenders(opts *bind.CallOpts) ([]common.Address, error) { + var out []interface{} + err := _AuthorizedForwarder.contract.Call(opts, &out, "getAuthorizedSenders") + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +func (_AuthorizedForwarder *AuthorizedForwarderSession) GetAuthorizedSenders() ([]common.Address, error) { + return _AuthorizedForwarder.Contract.GetAuthorizedSenders(&_AuthorizedForwarder.CallOpts) +} + +func (_AuthorizedForwarder *AuthorizedForwarderCallerSession) GetAuthorizedSenders() ([]common.Address, error) { + return _AuthorizedForwarder.Contract.GetAuthorizedSenders(&_AuthorizedForwarder.CallOpts) +} + +func (_AuthorizedForwarder *AuthorizedForwarderCaller) IsAuthorizedSender(opts *bind.CallOpts, sender common.Address) (bool, error) { + var out []interface{} + err := _AuthorizedForwarder.contract.Call(opts, &out, "isAuthorizedSender", sender) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_AuthorizedForwarder *AuthorizedForwarderSession) IsAuthorizedSender(sender common.Address) (bool, error) { + return _AuthorizedForwarder.Contract.IsAuthorizedSender(&_AuthorizedForwarder.CallOpts, sender) +} + +func (_AuthorizedForwarder *AuthorizedForwarderCallerSession) IsAuthorizedSender(sender common.Address) (bool, error) { + return _AuthorizedForwarder.Contract.IsAuthorizedSender(&_AuthorizedForwarder.CallOpts, sender) +} + +func (_AuthorizedForwarder *AuthorizedForwarderCaller) LinkToken(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _AuthorizedForwarder.contract.Call(opts, &out, "linkToken") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_AuthorizedForwarder *AuthorizedForwarderSession) LinkToken() (common.Address, error) { + return _AuthorizedForwarder.Contract.LinkToken(&_AuthorizedForwarder.CallOpts) +} + +func (_AuthorizedForwarder *AuthorizedForwarderCallerSession) LinkToken() (common.Address, error) { + return _AuthorizedForwarder.Contract.LinkToken(&_AuthorizedForwarder.CallOpts) +} + +func (_AuthorizedForwarder *AuthorizedForwarderCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _AuthorizedForwarder.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_AuthorizedForwarder *AuthorizedForwarderSession) Owner() (common.Address, error) { + return _AuthorizedForwarder.Contract.Owner(&_AuthorizedForwarder.CallOpts) +} + +func (_AuthorizedForwarder *AuthorizedForwarderCallerSession) Owner() (common.Address, error) { + return _AuthorizedForwarder.Contract.Owner(&_AuthorizedForwarder.CallOpts) +} + +func (_AuthorizedForwarder *AuthorizedForwarderCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _AuthorizedForwarder.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_AuthorizedForwarder *AuthorizedForwarderSession) TypeAndVersion() (string, error) { + return _AuthorizedForwarder.Contract.TypeAndVersion(&_AuthorizedForwarder.CallOpts) +} + +func (_AuthorizedForwarder *AuthorizedForwarderCallerSession) TypeAndVersion() (string, error) { + return _AuthorizedForwarder.Contract.TypeAndVersion(&_AuthorizedForwarder.CallOpts) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AuthorizedForwarder.contract.Transact(opts, "acceptOwnership") +} + +func (_AuthorizedForwarder *AuthorizedForwarderSession) AcceptOwnership() (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.AcceptOwnership(&_AuthorizedForwarder.TransactOpts) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.AcceptOwnership(&_AuthorizedForwarder.TransactOpts) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactor) Forward(opts *bind.TransactOpts, to common.Address, data []byte) (*types.Transaction, error) { + return _AuthorizedForwarder.contract.Transact(opts, "forward", to, data) +} + +func (_AuthorizedForwarder *AuthorizedForwarderSession) Forward(to common.Address, data []byte) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.Forward(&_AuthorizedForwarder.TransactOpts, to, data) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactorSession) Forward(to common.Address, data []byte) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.Forward(&_AuthorizedForwarder.TransactOpts, to, data) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactor) MultiForward(opts *bind.TransactOpts, tos []common.Address, datas [][]byte) (*types.Transaction, error) { + return _AuthorizedForwarder.contract.Transact(opts, "multiForward", tos, datas) +} + +func (_AuthorizedForwarder *AuthorizedForwarderSession) MultiForward(tos []common.Address, datas [][]byte) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.MultiForward(&_AuthorizedForwarder.TransactOpts, tos, datas) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactorSession) MultiForward(tos []common.Address, datas [][]byte) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.MultiForward(&_AuthorizedForwarder.TransactOpts, tos, datas) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactor) OwnerForward(opts *bind.TransactOpts, to common.Address, data []byte) (*types.Transaction, error) { + return _AuthorizedForwarder.contract.Transact(opts, "ownerForward", to, data) +} + +func (_AuthorizedForwarder *AuthorizedForwarderSession) OwnerForward(to common.Address, data []byte) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.OwnerForward(&_AuthorizedForwarder.TransactOpts, to, data) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactorSession) OwnerForward(to common.Address, data []byte) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.OwnerForward(&_AuthorizedForwarder.TransactOpts, to, data) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactor) SetAuthorizedSenders(opts *bind.TransactOpts, senders []common.Address) (*types.Transaction, error) { + return _AuthorizedForwarder.contract.Transact(opts, "setAuthorizedSenders", senders) +} + +func (_AuthorizedForwarder *AuthorizedForwarderSession) SetAuthorizedSenders(senders []common.Address) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.SetAuthorizedSenders(&_AuthorizedForwarder.TransactOpts, senders) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactorSession) SetAuthorizedSenders(senders []common.Address) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.SetAuthorizedSenders(&_AuthorizedForwarder.TransactOpts, senders) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _AuthorizedForwarder.contract.Transact(opts, "transferOwnership", to) +} + +func (_AuthorizedForwarder *AuthorizedForwarderSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.TransferOwnership(&_AuthorizedForwarder.TransactOpts, to) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.TransferOwnership(&_AuthorizedForwarder.TransactOpts, to) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactor) TransferOwnershipWithMessage(opts *bind.TransactOpts, to common.Address, message []byte) (*types.Transaction, error) { + return _AuthorizedForwarder.contract.Transact(opts, "transferOwnershipWithMessage", to, message) +} + +func (_AuthorizedForwarder *AuthorizedForwarderSession) TransferOwnershipWithMessage(to common.Address, message []byte) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.TransferOwnershipWithMessage(&_AuthorizedForwarder.TransactOpts, to, message) +} + +func (_AuthorizedForwarder *AuthorizedForwarderTransactorSession) TransferOwnershipWithMessage(to common.Address, message []byte) (*types.Transaction, error) { + return _AuthorizedForwarder.Contract.TransferOwnershipWithMessage(&_AuthorizedForwarder.TransactOpts, to, message) +} + +type AuthorizedForwarderAuthorizedSendersChangedIterator struct { + Event *AuthorizedForwarderAuthorizedSendersChanged + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AuthorizedForwarderAuthorizedSendersChangedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AuthorizedForwarderAuthorizedSendersChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AuthorizedForwarderAuthorizedSendersChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AuthorizedForwarderAuthorizedSendersChangedIterator) Error() error { + return it.fail +} + +func (it *AuthorizedForwarderAuthorizedSendersChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AuthorizedForwarderAuthorizedSendersChanged struct { + Senders []common.Address + ChangedBy common.Address + Raw types.Log +} + +func (_AuthorizedForwarder *AuthorizedForwarderFilterer) FilterAuthorizedSendersChanged(opts *bind.FilterOpts) (*AuthorizedForwarderAuthorizedSendersChangedIterator, error) { + + logs, sub, err := _AuthorizedForwarder.contract.FilterLogs(opts, "AuthorizedSendersChanged") + if err != nil { + return nil, err + } + return &AuthorizedForwarderAuthorizedSendersChangedIterator{contract: _AuthorizedForwarder.contract, event: "AuthorizedSendersChanged", logs: logs, sub: sub}, nil +} + +func (_AuthorizedForwarder *AuthorizedForwarderFilterer) WatchAuthorizedSendersChanged(opts *bind.WatchOpts, sink chan<- *AuthorizedForwarderAuthorizedSendersChanged) (event.Subscription, error) { + + logs, sub, err := _AuthorizedForwarder.contract.WatchLogs(opts, "AuthorizedSendersChanged") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AuthorizedForwarderAuthorizedSendersChanged) + if err := _AuthorizedForwarder.contract.UnpackLog(event, "AuthorizedSendersChanged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AuthorizedForwarder *AuthorizedForwarderFilterer) ParseAuthorizedSendersChanged(log types.Log) (*AuthorizedForwarderAuthorizedSendersChanged, error) { + event := new(AuthorizedForwarderAuthorizedSendersChanged) + if err := _AuthorizedForwarder.contract.UnpackLog(event, "AuthorizedSendersChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AuthorizedForwarderOwnershipTransferRequestedIterator struct { + Event *AuthorizedForwarderOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AuthorizedForwarderOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AuthorizedForwarderOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AuthorizedForwarderOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AuthorizedForwarderOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *AuthorizedForwarderOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AuthorizedForwarderOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_AuthorizedForwarder *AuthorizedForwarderFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*AuthorizedForwarderOwnershipTransferRequestedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AuthorizedForwarder.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &AuthorizedForwarderOwnershipTransferRequestedIterator{contract: _AuthorizedForwarder.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_AuthorizedForwarder *AuthorizedForwarderFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *AuthorizedForwarderOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AuthorizedForwarder.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AuthorizedForwarderOwnershipTransferRequested) + if err := _AuthorizedForwarder.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AuthorizedForwarder *AuthorizedForwarderFilterer) ParseOwnershipTransferRequested(log types.Log) (*AuthorizedForwarderOwnershipTransferRequested, error) { + event := new(AuthorizedForwarderOwnershipTransferRequested) + if err := _AuthorizedForwarder.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AuthorizedForwarderOwnershipTransferRequestedWithMessageIterator struct { + Event *AuthorizedForwarderOwnershipTransferRequestedWithMessage + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AuthorizedForwarderOwnershipTransferRequestedWithMessageIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AuthorizedForwarderOwnershipTransferRequestedWithMessage) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AuthorizedForwarderOwnershipTransferRequestedWithMessage) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AuthorizedForwarderOwnershipTransferRequestedWithMessageIterator) Error() error { + return it.fail +} + +func (it *AuthorizedForwarderOwnershipTransferRequestedWithMessageIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AuthorizedForwarderOwnershipTransferRequestedWithMessage struct { + From common.Address + To common.Address + Message []byte + Raw types.Log +} + +func (_AuthorizedForwarder *AuthorizedForwarderFilterer) FilterOwnershipTransferRequestedWithMessage(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*AuthorizedForwarderOwnershipTransferRequestedWithMessageIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AuthorizedForwarder.contract.FilterLogs(opts, "OwnershipTransferRequestedWithMessage", fromRule, toRule) + if err != nil { + return nil, err + } + return &AuthorizedForwarderOwnershipTransferRequestedWithMessageIterator{contract: _AuthorizedForwarder.contract, event: "OwnershipTransferRequestedWithMessage", logs: logs, sub: sub}, nil +} + +func (_AuthorizedForwarder *AuthorizedForwarderFilterer) WatchOwnershipTransferRequestedWithMessage(opts *bind.WatchOpts, sink chan<- *AuthorizedForwarderOwnershipTransferRequestedWithMessage, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AuthorizedForwarder.contract.WatchLogs(opts, "OwnershipTransferRequestedWithMessage", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AuthorizedForwarderOwnershipTransferRequestedWithMessage) + if err := _AuthorizedForwarder.contract.UnpackLog(event, "OwnershipTransferRequestedWithMessage", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AuthorizedForwarder *AuthorizedForwarderFilterer) ParseOwnershipTransferRequestedWithMessage(log types.Log) (*AuthorizedForwarderOwnershipTransferRequestedWithMessage, error) { + event := new(AuthorizedForwarderOwnershipTransferRequestedWithMessage) + if err := _AuthorizedForwarder.contract.UnpackLog(event, "OwnershipTransferRequestedWithMessage", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type AuthorizedForwarderOwnershipTransferredIterator struct { + Event *AuthorizedForwarderOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AuthorizedForwarderOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AuthorizedForwarderOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AuthorizedForwarderOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AuthorizedForwarderOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *AuthorizedForwarderOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AuthorizedForwarderOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_AuthorizedForwarder *AuthorizedForwarderFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*AuthorizedForwarderOwnershipTransferredIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AuthorizedForwarder.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &AuthorizedForwarderOwnershipTransferredIterator{contract: _AuthorizedForwarder.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_AuthorizedForwarder *AuthorizedForwarderFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *AuthorizedForwarderOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _AuthorizedForwarder.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AuthorizedForwarderOwnershipTransferred) + if err := _AuthorizedForwarder.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AuthorizedForwarder *AuthorizedForwarderFilterer) ParseOwnershipTransferred(log types.Log) (*AuthorizedForwarderOwnershipTransferred, error) { + event := new(AuthorizedForwarderOwnershipTransferred) + if err := _AuthorizedForwarder.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_AuthorizedForwarder *AuthorizedForwarder) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _AuthorizedForwarder.abi.Events["AuthorizedSendersChanged"].ID: + return _AuthorizedForwarder.ParseAuthorizedSendersChanged(log) + case _AuthorizedForwarder.abi.Events["OwnershipTransferRequested"].ID: + return _AuthorizedForwarder.ParseOwnershipTransferRequested(log) + case _AuthorizedForwarder.abi.Events["OwnershipTransferRequestedWithMessage"].ID: + return _AuthorizedForwarder.ParseOwnershipTransferRequestedWithMessage(log) + case _AuthorizedForwarder.abi.Events["OwnershipTransferred"].ID: + return _AuthorizedForwarder.ParseOwnershipTransferred(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (AuthorizedForwarderAuthorizedSendersChanged) Topic() common.Hash { + return common.HexToHash("0xf263cfb3e4298332e776194610cf9fdc09ccb3ada8b9aa39764d882e11fbf0a0") +} + +func (AuthorizedForwarderOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (AuthorizedForwarderOwnershipTransferRequestedWithMessage) Topic() common.Hash { + return common.HexToHash("0x4e1e878dc28d5f040db5969163ff1acd75c44c3f655da2dde9c70bbd8e56dc7e") +} + +func (AuthorizedForwarderOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (_AuthorizedForwarder *AuthorizedForwarder) Address() common.Address { + return _AuthorizedForwarder.address +} + +type AuthorizedForwarderInterface interface { + GetAuthorizedSenders(opts *bind.CallOpts) ([]common.Address, error) + + IsAuthorizedSender(opts *bind.CallOpts, sender common.Address) (bool, error) + + LinkToken(opts *bind.CallOpts) (common.Address, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + Forward(opts *bind.TransactOpts, to common.Address, data []byte) (*types.Transaction, error) + + MultiForward(opts *bind.TransactOpts, tos []common.Address, datas [][]byte) (*types.Transaction, error) + + OwnerForward(opts *bind.TransactOpts, to common.Address, data []byte) (*types.Transaction, error) + + SetAuthorizedSenders(opts *bind.TransactOpts, senders []common.Address) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + TransferOwnershipWithMessage(opts *bind.TransactOpts, to common.Address, message []byte) (*types.Transaction, error) + + FilterAuthorizedSendersChanged(opts *bind.FilterOpts) (*AuthorizedForwarderAuthorizedSendersChangedIterator, error) + + WatchAuthorizedSendersChanged(opts *bind.WatchOpts, sink chan<- *AuthorizedForwarderAuthorizedSendersChanged) (event.Subscription, error) + + ParseAuthorizedSendersChanged(log types.Log) (*AuthorizedForwarderAuthorizedSendersChanged, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*AuthorizedForwarderOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *AuthorizedForwarderOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*AuthorizedForwarderOwnershipTransferRequested, error) + + FilterOwnershipTransferRequestedWithMessage(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*AuthorizedForwarderOwnershipTransferRequestedWithMessageIterator, error) + + WatchOwnershipTransferRequestedWithMessage(opts *bind.WatchOpts, sink chan<- *AuthorizedForwarderOwnershipTransferRequestedWithMessage, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequestedWithMessage(log types.Log) (*AuthorizedForwarderOwnershipTransferRequestedWithMessage, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*AuthorizedForwarderOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *AuthorizedForwarderOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*AuthorizedForwarderOwnershipTransferred, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/operatorforwarder/generated/authorized_receiver/authorized_receiver.go b/core/gethwrappers/operatorforwarder/generated/authorized_receiver/authorized_receiver.go new file mode 100644 index 00000000000..632d08b294b --- /dev/null +++ b/core/gethwrappers/operatorforwarder/generated/authorized_receiver/authorized_receiver.go @@ -0,0 +1,363 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package authorized_receiver + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +var AuthorizedReceiverMetaData = &bind.MetaData{ + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"changedBy\",\"type\":\"address\"}],\"name\":\"AuthorizedSendersChanged\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"getAuthorizedSenders\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"isAuthorizedSender\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"setAuthorizedSenders\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", +} + +var AuthorizedReceiverABI = AuthorizedReceiverMetaData.ABI + +type AuthorizedReceiver struct { + address common.Address + abi abi.ABI + AuthorizedReceiverCaller + AuthorizedReceiverTransactor + AuthorizedReceiverFilterer +} + +type AuthorizedReceiverCaller struct { + contract *bind.BoundContract +} + +type AuthorizedReceiverTransactor struct { + contract *bind.BoundContract +} + +type AuthorizedReceiverFilterer struct { + contract *bind.BoundContract +} + +type AuthorizedReceiverSession struct { + Contract *AuthorizedReceiver + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type AuthorizedReceiverCallerSession struct { + Contract *AuthorizedReceiverCaller + CallOpts bind.CallOpts +} + +type AuthorizedReceiverTransactorSession struct { + Contract *AuthorizedReceiverTransactor + TransactOpts bind.TransactOpts +} + +type AuthorizedReceiverRaw struct { + Contract *AuthorizedReceiver +} + +type AuthorizedReceiverCallerRaw struct { + Contract *AuthorizedReceiverCaller +} + +type AuthorizedReceiverTransactorRaw struct { + Contract *AuthorizedReceiverTransactor +} + +func NewAuthorizedReceiver(address common.Address, backend bind.ContractBackend) (*AuthorizedReceiver, error) { + abi, err := abi.JSON(strings.NewReader(AuthorizedReceiverABI)) + if err != nil { + return nil, err + } + contract, err := bindAuthorizedReceiver(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &AuthorizedReceiver{address: address, abi: abi, AuthorizedReceiverCaller: AuthorizedReceiverCaller{contract: contract}, AuthorizedReceiverTransactor: AuthorizedReceiverTransactor{contract: contract}, AuthorizedReceiverFilterer: AuthorizedReceiverFilterer{contract: contract}}, nil +} + +func NewAuthorizedReceiverCaller(address common.Address, caller bind.ContractCaller) (*AuthorizedReceiverCaller, error) { + contract, err := bindAuthorizedReceiver(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &AuthorizedReceiverCaller{contract: contract}, nil +} + +func NewAuthorizedReceiverTransactor(address common.Address, transactor bind.ContractTransactor) (*AuthorizedReceiverTransactor, error) { + contract, err := bindAuthorizedReceiver(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &AuthorizedReceiverTransactor{contract: contract}, nil +} + +func NewAuthorizedReceiverFilterer(address common.Address, filterer bind.ContractFilterer) (*AuthorizedReceiverFilterer, error) { + contract, err := bindAuthorizedReceiver(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &AuthorizedReceiverFilterer{contract: contract}, nil +} + +func bindAuthorizedReceiver(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := AuthorizedReceiverMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_AuthorizedReceiver *AuthorizedReceiverRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AuthorizedReceiver.Contract.AuthorizedReceiverCaller.contract.Call(opts, result, method, params...) +} + +func (_AuthorizedReceiver *AuthorizedReceiverRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AuthorizedReceiver.Contract.AuthorizedReceiverTransactor.contract.Transfer(opts) +} + +func (_AuthorizedReceiver *AuthorizedReceiverRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AuthorizedReceiver.Contract.AuthorizedReceiverTransactor.contract.Transact(opts, method, params...) +} + +func (_AuthorizedReceiver *AuthorizedReceiverCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _AuthorizedReceiver.Contract.contract.Call(opts, result, method, params...) +} + +func (_AuthorizedReceiver *AuthorizedReceiverTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _AuthorizedReceiver.Contract.contract.Transfer(opts) +} + +func (_AuthorizedReceiver *AuthorizedReceiverTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _AuthorizedReceiver.Contract.contract.Transact(opts, method, params...) +} + +func (_AuthorizedReceiver *AuthorizedReceiverCaller) GetAuthorizedSenders(opts *bind.CallOpts) ([]common.Address, error) { + var out []interface{} + err := _AuthorizedReceiver.contract.Call(opts, &out, "getAuthorizedSenders") + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +func (_AuthorizedReceiver *AuthorizedReceiverSession) GetAuthorizedSenders() ([]common.Address, error) { + return _AuthorizedReceiver.Contract.GetAuthorizedSenders(&_AuthorizedReceiver.CallOpts) +} + +func (_AuthorizedReceiver *AuthorizedReceiverCallerSession) GetAuthorizedSenders() ([]common.Address, error) { + return _AuthorizedReceiver.Contract.GetAuthorizedSenders(&_AuthorizedReceiver.CallOpts) +} + +func (_AuthorizedReceiver *AuthorizedReceiverCaller) IsAuthorizedSender(opts *bind.CallOpts, sender common.Address) (bool, error) { + var out []interface{} + err := _AuthorizedReceiver.contract.Call(opts, &out, "isAuthorizedSender", sender) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_AuthorizedReceiver *AuthorizedReceiverSession) IsAuthorizedSender(sender common.Address) (bool, error) { + return _AuthorizedReceiver.Contract.IsAuthorizedSender(&_AuthorizedReceiver.CallOpts, sender) +} + +func (_AuthorizedReceiver *AuthorizedReceiverCallerSession) IsAuthorizedSender(sender common.Address) (bool, error) { + return _AuthorizedReceiver.Contract.IsAuthorizedSender(&_AuthorizedReceiver.CallOpts, sender) +} + +func (_AuthorizedReceiver *AuthorizedReceiverTransactor) SetAuthorizedSenders(opts *bind.TransactOpts, senders []common.Address) (*types.Transaction, error) { + return _AuthorizedReceiver.contract.Transact(opts, "setAuthorizedSenders", senders) +} + +func (_AuthorizedReceiver *AuthorizedReceiverSession) SetAuthorizedSenders(senders []common.Address) (*types.Transaction, error) { + return _AuthorizedReceiver.Contract.SetAuthorizedSenders(&_AuthorizedReceiver.TransactOpts, senders) +} + +func (_AuthorizedReceiver *AuthorizedReceiverTransactorSession) SetAuthorizedSenders(senders []common.Address) (*types.Transaction, error) { + return _AuthorizedReceiver.Contract.SetAuthorizedSenders(&_AuthorizedReceiver.TransactOpts, senders) +} + +type AuthorizedReceiverAuthorizedSendersChangedIterator struct { + Event *AuthorizedReceiverAuthorizedSendersChanged + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *AuthorizedReceiverAuthorizedSendersChangedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(AuthorizedReceiverAuthorizedSendersChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(AuthorizedReceiverAuthorizedSendersChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *AuthorizedReceiverAuthorizedSendersChangedIterator) Error() error { + return it.fail +} + +func (it *AuthorizedReceiverAuthorizedSendersChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type AuthorizedReceiverAuthorizedSendersChanged struct { + Senders []common.Address + ChangedBy common.Address + Raw types.Log +} + +func (_AuthorizedReceiver *AuthorizedReceiverFilterer) FilterAuthorizedSendersChanged(opts *bind.FilterOpts) (*AuthorizedReceiverAuthorizedSendersChangedIterator, error) { + + logs, sub, err := _AuthorizedReceiver.contract.FilterLogs(opts, "AuthorizedSendersChanged") + if err != nil { + return nil, err + } + return &AuthorizedReceiverAuthorizedSendersChangedIterator{contract: _AuthorizedReceiver.contract, event: "AuthorizedSendersChanged", logs: logs, sub: sub}, nil +} + +func (_AuthorizedReceiver *AuthorizedReceiverFilterer) WatchAuthorizedSendersChanged(opts *bind.WatchOpts, sink chan<- *AuthorizedReceiverAuthorizedSendersChanged) (event.Subscription, error) { + + logs, sub, err := _AuthorizedReceiver.contract.WatchLogs(opts, "AuthorizedSendersChanged") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(AuthorizedReceiverAuthorizedSendersChanged) + if err := _AuthorizedReceiver.contract.UnpackLog(event, "AuthorizedSendersChanged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_AuthorizedReceiver *AuthorizedReceiverFilterer) ParseAuthorizedSendersChanged(log types.Log) (*AuthorizedReceiverAuthorizedSendersChanged, error) { + event := new(AuthorizedReceiverAuthorizedSendersChanged) + if err := _AuthorizedReceiver.contract.UnpackLog(event, "AuthorizedSendersChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_AuthorizedReceiver *AuthorizedReceiver) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _AuthorizedReceiver.abi.Events["AuthorizedSendersChanged"].ID: + return _AuthorizedReceiver.ParseAuthorizedSendersChanged(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (AuthorizedReceiverAuthorizedSendersChanged) Topic() common.Hash { + return common.HexToHash("0xf263cfb3e4298332e776194610cf9fdc09ccb3ada8b9aa39764d882e11fbf0a0") +} + +func (_AuthorizedReceiver *AuthorizedReceiver) Address() common.Address { + return _AuthorizedReceiver.address +} + +type AuthorizedReceiverInterface interface { + GetAuthorizedSenders(opts *bind.CallOpts) ([]common.Address, error) + + IsAuthorizedSender(opts *bind.CallOpts, sender common.Address) (bool, error) + + SetAuthorizedSenders(opts *bind.TransactOpts, senders []common.Address) (*types.Transaction, error) + + FilterAuthorizedSendersChanged(opts *bind.FilterOpts) (*AuthorizedReceiverAuthorizedSendersChangedIterator, error) + + WatchAuthorizedSendersChanged(opts *bind.WatchOpts, sink chan<- *AuthorizedReceiverAuthorizedSendersChanged) (event.Subscription, error) + + ParseAuthorizedSendersChanged(log types.Log) (*AuthorizedReceiverAuthorizedSendersChanged, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/operatorforwarder/generated/link_token_receiver/link_token_receiver.go b/core/gethwrappers/operatorforwarder/generated/link_token_receiver/link_token_receiver.go new file mode 100644 index 00000000000..8a26281dbbb --- /dev/null +++ b/core/gethwrappers/operatorforwarder/generated/link_token_receiver/link_token_receiver.go @@ -0,0 +1,197 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package link_token_receiver + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +var LinkTokenReceiverMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"name\":\"getChainlinkToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", +} + +var LinkTokenReceiverABI = LinkTokenReceiverMetaData.ABI + +type LinkTokenReceiver struct { + address common.Address + abi abi.ABI + LinkTokenReceiverCaller + LinkTokenReceiverTransactor + LinkTokenReceiverFilterer +} + +type LinkTokenReceiverCaller struct { + contract *bind.BoundContract +} + +type LinkTokenReceiverTransactor struct { + contract *bind.BoundContract +} + +type LinkTokenReceiverFilterer struct { + contract *bind.BoundContract +} + +type LinkTokenReceiverSession struct { + Contract *LinkTokenReceiver + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type LinkTokenReceiverCallerSession struct { + Contract *LinkTokenReceiverCaller + CallOpts bind.CallOpts +} + +type LinkTokenReceiverTransactorSession struct { + Contract *LinkTokenReceiverTransactor + TransactOpts bind.TransactOpts +} + +type LinkTokenReceiverRaw struct { + Contract *LinkTokenReceiver +} + +type LinkTokenReceiverCallerRaw struct { + Contract *LinkTokenReceiverCaller +} + +type LinkTokenReceiverTransactorRaw struct { + Contract *LinkTokenReceiverTransactor +} + +func NewLinkTokenReceiver(address common.Address, backend bind.ContractBackend) (*LinkTokenReceiver, error) { + abi, err := abi.JSON(strings.NewReader(LinkTokenReceiverABI)) + if err != nil { + return nil, err + } + contract, err := bindLinkTokenReceiver(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &LinkTokenReceiver{address: address, abi: abi, LinkTokenReceiverCaller: LinkTokenReceiverCaller{contract: contract}, LinkTokenReceiverTransactor: LinkTokenReceiverTransactor{contract: contract}, LinkTokenReceiverFilterer: LinkTokenReceiverFilterer{contract: contract}}, nil +} + +func NewLinkTokenReceiverCaller(address common.Address, caller bind.ContractCaller) (*LinkTokenReceiverCaller, error) { + contract, err := bindLinkTokenReceiver(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &LinkTokenReceiverCaller{contract: contract}, nil +} + +func NewLinkTokenReceiverTransactor(address common.Address, transactor bind.ContractTransactor) (*LinkTokenReceiverTransactor, error) { + contract, err := bindLinkTokenReceiver(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &LinkTokenReceiverTransactor{contract: contract}, nil +} + +func NewLinkTokenReceiverFilterer(address common.Address, filterer bind.ContractFilterer) (*LinkTokenReceiverFilterer, error) { + contract, err := bindLinkTokenReceiver(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &LinkTokenReceiverFilterer{contract: contract}, nil +} + +func bindLinkTokenReceiver(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := LinkTokenReceiverMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_LinkTokenReceiver *LinkTokenReceiverRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _LinkTokenReceiver.Contract.LinkTokenReceiverCaller.contract.Call(opts, result, method, params...) +} + +func (_LinkTokenReceiver *LinkTokenReceiverRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _LinkTokenReceiver.Contract.LinkTokenReceiverTransactor.contract.Transfer(opts) +} + +func (_LinkTokenReceiver *LinkTokenReceiverRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _LinkTokenReceiver.Contract.LinkTokenReceiverTransactor.contract.Transact(opts, method, params...) +} + +func (_LinkTokenReceiver *LinkTokenReceiverCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _LinkTokenReceiver.Contract.contract.Call(opts, result, method, params...) +} + +func (_LinkTokenReceiver *LinkTokenReceiverTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _LinkTokenReceiver.Contract.contract.Transfer(opts) +} + +func (_LinkTokenReceiver *LinkTokenReceiverTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _LinkTokenReceiver.Contract.contract.Transact(opts, method, params...) +} + +func (_LinkTokenReceiver *LinkTokenReceiverCaller) GetChainlinkToken(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _LinkTokenReceiver.contract.Call(opts, &out, "getChainlinkToken") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_LinkTokenReceiver *LinkTokenReceiverSession) GetChainlinkToken() (common.Address, error) { + return _LinkTokenReceiver.Contract.GetChainlinkToken(&_LinkTokenReceiver.CallOpts) +} + +func (_LinkTokenReceiver *LinkTokenReceiverCallerSession) GetChainlinkToken() (common.Address, error) { + return _LinkTokenReceiver.Contract.GetChainlinkToken(&_LinkTokenReceiver.CallOpts) +} + +func (_LinkTokenReceiver *LinkTokenReceiverTransactor) OnTokenTransfer(opts *bind.TransactOpts, sender common.Address, amount *big.Int, data []byte) (*types.Transaction, error) { + return _LinkTokenReceiver.contract.Transact(opts, "onTokenTransfer", sender, amount, data) +} + +func (_LinkTokenReceiver *LinkTokenReceiverSession) OnTokenTransfer(sender common.Address, amount *big.Int, data []byte) (*types.Transaction, error) { + return _LinkTokenReceiver.Contract.OnTokenTransfer(&_LinkTokenReceiver.TransactOpts, sender, amount, data) +} + +func (_LinkTokenReceiver *LinkTokenReceiverTransactorSession) OnTokenTransfer(sender common.Address, amount *big.Int, data []byte) (*types.Transaction, error) { + return _LinkTokenReceiver.Contract.OnTokenTransfer(&_LinkTokenReceiver.TransactOpts, sender, amount, data) +} + +func (_LinkTokenReceiver *LinkTokenReceiver) Address() common.Address { + return _LinkTokenReceiver.address +} + +type LinkTokenReceiverInterface interface { + GetChainlinkToken(opts *bind.CallOpts) (common.Address, error) + + OnTokenTransfer(opts *bind.TransactOpts, sender common.Address, amount *big.Int, data []byte) (*types.Transaction, error) + + Address() common.Address +} diff --git a/core/gethwrappers/operatorforwarder/generated/operator/operator.go b/core/gethwrappers/operatorforwarder/generated/operator/operator.go new file mode 100644 index 00000000000..71004cea91c --- /dev/null +++ b/core/gethwrappers/operatorforwarder/generated/operator/operator.go @@ -0,0 +1,1731 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package operator + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +var OperatorMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"link\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"changedBy\",\"type\":\"address\"}],\"name\":\"AuthorizedSendersChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"CancelOracleRequest\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"specId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"payment\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"callbackAddr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes4\",\"name\":\"callbackFunctionId\",\"type\":\"bytes4\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"cancelExpiration\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"dataVersion\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"OracleRequest\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"OracleResponse\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"acceptedContract\",\"type\":\"address\"}],\"name\":\"OwnableContractAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"changedBy\",\"type\":\"address\"}],\"name\":\"TargetsUpdatedAuthorizedSenders\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"EXPIRYTIME\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"acceptAuthorizedReceivers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"ownable\",\"type\":\"address[]\"}],\"name\":\"acceptOwnableContracts\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"payment\",\"type\":\"uint256\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunc\",\"type\":\"bytes4\"},{\"internalType\":\"uint256\",\"name\":\"expiration\",\"type\":\"uint256\"}],\"name\":\"cancelOracleRequest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"payment\",\"type\":\"uint256\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunc\",\"type\":\"bytes4\"},{\"internalType\":\"uint256\",\"name\":\"expiration\",\"type\":\"uint256\"}],\"name\":\"cancelOracleRequestByRequester\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable[]\",\"name\":\"receivers\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"name\":\"distributeFunds\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"payment\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"callbackAddress\",\"type\":\"address\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunctionId\",\"type\":\"bytes4\"},{\"internalType\":\"uint256\",\"name\":\"expiration\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\"}],\"name\":\"fulfillOracleRequest\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"payment\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"callbackAddress\",\"type\":\"address\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunctionId\",\"type\":\"bytes4\"},{\"internalType\":\"uint256\",\"name\":\"expiration\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"fulfillOracleRequest2\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAuthorizedSenders\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainlinkToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"isAuthorizedSender\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"payment\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"specId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunctionId\",\"type\":\"bytes4\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"dataVersion\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"operatorRequest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"payment\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"specId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callbackAddress\",\"type\":\"address\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunctionId\",\"type\":\"bytes4\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"dataVersion\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"oracleRequest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"ownerForward\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"ownerTransferAndCall\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"setAuthorizedSenders\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"targets\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"setAuthorizedSendersOn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"ownable\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnableContracts\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60a060405260016006553480156200001657600080fd5b5060405162003aef38038062003aef8339810160408190526200003991620001ab565b808060006001600160a01b038216620000995760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600280546001600160a01b0319166001600160a01b0384811691909117909155811615620000cc57620000cc81620000e2565b505050506001600160a01b0316608052620001e3565b336001600160a01b038216036200013c5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000090565b600380546001600160a01b0319166001600160a01b03838116918217909255600254604051919216907fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae127890600090a350565b80516001600160a01b0381168114620001a657600080fd5b919050565b60008060408385031215620001bf57600080fd5b620001ca836200018e565b9150620001da602084016200018e565b90509250929050565b6080516138b16200023e600039600081816101ec0152818161075e015281816109f601528181610c520152818161189601528181611b0001528181611ba00152818161217e0152818161243101526129b901526138b16000f3fe6080604052600436106101965760003560e01c80636ae0bc76116100e1578063a4c0ed361161008a578063f2fde38b11610064578063f2fde38b146104aa578063f3fef3a3146104ca578063fa00763a146104ea578063fc4a03ed1461053057600080fd5b8063a4c0ed361461044a578063eb007d991461046a578063ee56997b1461048a57600080fd5b806379ba5097116100bb57806379ba5097146103ea5780638da5cb5b146103ff578063902fc3701461042a57600080fd5b80636ae0bc76146103975780636bd59ec0146103b75780636ee4d553146103ca57600080fd5b80633ec5bc1411610143578063501883011161011d578063501883011461033e57806352043783146103615780635ffa62881461037757600080fd5b80633ec5bc14146102ce57806340429946146102ee5780634ab0d1901461030e57600080fd5b8063181f5a7711610174578063181f5a77146102365780632408afaa1461028c5780633c6d41b9146102ae57600080fd5b806301994b991461019b578063033f49f7146101bd578063165d35e1146101dd575b600080fd5b3480156101a757600080fd5b506101bb6101b6366004612e2c565b610550565b005b3480156101c957600080fd5b506101bb6101d8366004612ed2565b610753565b3480156101e957600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561024257600080fd5b5061027f6040518060400160405280600e81526020017f4f70657261746f7220312e302e3000000000000000000000000000000000000081525081565b60405161022d9190612f4b565b34801561029857600080fd5b506102a161096f565b60405161022d9190612f9c565b3480156102ba57600080fd5b506101bb6102c936600461302b565b6109de565b3480156102da57600080fd5b506101bb6102e93660046130b8565b610ae6565b3480156102fa57600080fd5b506101bb61030936600461310f565b610c3a565b34801561031a57600080fd5b5061032e6103293660046131b2565b610d43565b604051901515815260200161022d565b34801561034a57600080fd5b50610353611039565b60405190815260200161022d565b34801561036d57600080fd5b5061035361012c81565b34801561038357600080fd5b506101bb61039236600461320c565b611048565b3480156103a357600080fd5b5061032e6103b2366004613278565b6110cc565b6101bb6103c536600461320c565b611448565b3480156103d657600080fd5b506101bb6103e53660046132fc565b611685565b3480156103f657600080fd5b506101bb611920565b34801561040b57600080fd5b5060025473ffffffffffffffffffffffffffffffffffffffff1661020c565b34801561043657600080fd5b5061032e610445366004613339565b611a21565b34801561045657600080fd5b506101bb6104653660046133b8565b611b88565b34801561047657600080fd5b506101bb6104853660046132fc565b611d16565b34801561049657600080fd5b506101bb6104a5366004612e2c565b611d70565b3480156104b657600080fd5b506101bb6104c53660046134a3565b61207e565b3480156104d657600080fd5b506101bb6104e53660046134c7565b612092565b3480156104f657600080fd5b5061032e6105053660046134a3565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205460ff1690565b34801561053c57600080fd5b506101bb61054b36600461320c565b6121f7565b610558612353565b6105c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f742073657420617574686f72697a65642073656e6465727300000060448201526064015b60405180910390fd5b60005b8181101561074e576001600560008585858181106105e6576105e66134f3565b90506020020160208101906105fb91906134a3565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055828282818110610660576106606134f3565b905060200201602081019061067591906134a3565b73ffffffffffffffffffffffffffffffffffffffff167f615a0c1cb00a60d4acd77ec67acf2f17f223ef0932d591052fabc33643fe7e8260405160405180910390a28282828181106106c9576106c96134f3565b90506020020160208101906106de91906134a3565b73ffffffffffffffffffffffffffffffffffffffff166379ba50976040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561072557600080fd5b505af1158015610739573d6000803e3d6000fd5b505050508061074790613551565b90506105c6565b505050565b61075b6123a8565b827f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610811576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f43616e6e6f742063616c6c20746f204c494e4b0000000000000000000000000060448201526064016105ba565b8373ffffffffffffffffffffffffffffffffffffffff163b600003610892576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d75737420666f727761726420746f206120636f6e747261637400000000000060448201526064016105ba565b60008473ffffffffffffffffffffffffffffffffffffffff1684846040516108bb929190613589565b6000604051808303816000865af19150503d80600081146108f8576040519150601f19603f3d011682016040523d82523d6000602084013e6108fd565b606091505b5050905080610968576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f466f727761726465642063616c6c206661696c6564000000000000000000000060448201526064016105ba565b5050505050565b606060018054806020026020016040519081016040528092919081815260200182805480156109d457602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116109a9575b5050505050905090565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610a7d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d75737420757365204c494e4b20746f6b656e0000000000000000000000000060448201526064016105ba565b600080610a8e8a8a8c8a8a8a61242b565b91509150877fd8d7ecc4800d25fa53ce0372f13a416d98907a7ef3d8d3bdd79cf4fe75529c658b848c8e8c878c8c8c604051610ad2999897969594939291906135e2565b60405180910390a250505050505050505050565b610aee6123a8565b60005b82811015610c3457600060056000868685818110610b1157610b116134f3565b9050602002016020810190610b2691906134a3565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055838382818110610b8b57610b8b6134f3565b9050602002016020810190610ba091906134a3565b6040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152919091169063f2fde38b90602401600060405180830381600087803b158015610c0b57600080fd5b505af1158015610c1f573d6000803e3d6000fd5b5050505080610c2d90613551565b9050610af1565b50505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610cd9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d75737420757365204c494e4b20746f6b656e0000000000000000000000000060448201526064016105ba565b600080610cea8b8b8a8a8a8a61242b565b91509150887fd8d7ecc4800d25fa53ce0372f13a416d98907a7ef3d8d3bdd79cf4fe75529c658c848d8f8c878c8c8c604051610d2e999897969594939291906135e2565b60405180910390a25050505050505050505050565b6000610d4d612709565b600087815260046020526040812054889160089190911b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169003610dee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4d757374206861766520612076616c696420726571756573744964000000000060448201526064016105ba565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260056020526040902054869060ff1615610e80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f43616e6e6f742063616c6c206f776e656420636f6e747261637400000000000060448201526064016105ba565b610e8f89898989896001612782565b60405189907f9e9bc7616d42c2835d05ae617e508454e63b30b934be8aa932ebc125e0e58a6490600090a262061a805a1015610f27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4d7573742070726f7669646520636f6e73756d657220656e6f7567682067617360448201526064016105ba565b60008773ffffffffffffffffffffffffffffffffffffffff16878b87604051602401610f5d929190918252602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051610fe6919061366d565b6000604051808303816000865af19150503d8060008114611023576040519150601f19603f3d011682016040523d82523d6000602084013e611028565b606091505b50909b9a5050505050505050505050565b600061104361297a565b905090565b611050612353565b6110b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f742073657420617574686f72697a65642073656e6465727300000060448201526064016105ba565b6110c08484610550565b610c34848484846121f7565b60006110d6612709565b600088815260046020526040812054899160089190911b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169003611177576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4d757374206861766520612076616c696420726571756573744964000000000060448201526064016105ba565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260056020526040902054879060ff1615611209576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f43616e6e6f742063616c6c206f776e656420636f6e747261637400000000000060448201526064016105ba565b8985856020811015611277576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f526573706f6e7365206d757374206265203e203332206279746573000000000060448201526064016105ba565b81358381146112e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f466972737420776f7264206d757374206265207265717565737449640000000060448201526064016105ba565b6112f18e8e8e8e8e6002612782565b6040518e907f9e9bc7616d42c2835d05ae617e508454e63b30b934be8aa932ebc125e0e58a6490600090a262061a805a1015611389576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4d7573742070726f7669646520636f6e73756d657220656e6f7567682067617360448201526064016105ba565b60008c73ffffffffffffffffffffffffffffffffffffffff168c8b8b6040516020016113b793929190613689565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526113ef9161366d565b6000604051808303816000865af19150503d806000811461142c576040519150601f19603f3d011682016040523d82523d6000602084013e611431565b606091505b509098505050505050505050979650505050505050565b821580159061145657508281145b6114bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c6964206172726179206c656e67746828732900000000000000000060448201526064016105ba565b3460005b8481101561161c5760008484838181106114dc576114dc6134f3565b90506020020135905080836114f191906136c5565b92506000878784818110611507576115076134f3565b905060200201602081019061151c91906134a3565b73ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611573576040519150601f19603f3d011682016040523d82523d6000602084013e611578565b606091505b5050905080611609576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016105ba565b50508061161590613551565b90506114c0565b508015610968576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f546f6f206d756368204554482073656e7400000000000000000000000000000060448201526064016105ba565b6040805160208082018690527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b16828401527fffffffff00000000000000000000000000000000000000000000000000000000851660548301526058808301859052835180840390910181526078909201909252805191012060009060008681526004602052604090205490915060081b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00908116908216146117a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f506172616d7320646f206e6f74206d617463682072657175657374204944000060448201526064016105ba565b42821115611812576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f52657175657374206973206e6f7420657870697265640000000000000000000060448201526064016105ba565b6000858152600460205260408082208290555186917fa7842b9ec549398102c0d91b1b9919b2f20558aefdadf57528a95c6cd3292e9391a2836006600082825461185c91906136c5565b90915550506040517fa9059cbb000000000000000000000000000000000000000000000000000000008152336004820152602481018590527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a9059cbb906044016020604051808303816000875af11580156118f4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191891906136de565b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633146119a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016105ba565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560038054909116905560405173ffffffffffffffffffffffffffffffffffffffff909116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a350565b6000611a2b6123a8565b8380611a3561297a565b1015611ac3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f416d6f756e74207265717565737465642069732067726561746572207468616e60448201527f20776974686472617761626c652062616c616e6365000000000000000000000060648201526084016105ba565b6040517f4000aea000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690634000aea090611b3b908990899089908990600401613700565b6020604051808303816000875af1158015611b5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b7e91906136de565b9695505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614611c27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d75737420757365204c494e4b20746f6b656e0000000000000000000000000060448201526064016105ba565b60208101518190611c388183612a43565b84602484015283604484015260003073ffffffffffffffffffffffffffffffffffffffff1684604051611c6b919061366d565b600060405180830381855af49150503d8060008114611ca6576040519150601f19603f3d011682016040523d82523d6000602084013e611cab565b606091505b5050905080611918576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f556e61626c6520746f206372656174652072657175657374000000000000000060448201526064016105ba565b6040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b16602082015260348101859052610c349060540160405160208183030381529060405280519060200120848484611685565b611d78612353565b611dde576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f742073657420617574686f72697a65642073656e6465727300000060448201526064016105ba565b80611e45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4d7573742068617665206174206c6561737420312073656e646572000000000060448201526064016105ba565b60015460005b81811015611eda57600080600060018481548110611e6b57611e6b6134f3565b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055611ed381613551565b9050611e4b565b5060005b8281101561203057600080858584818110611efb57611efb6134f3565b9050602002016020810190611f1091906134a3565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000205460ff1615611fa1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4d757374206e6f742068617665206475706c69636174652073656e646572730060448201526064016105ba565b6001600080868685818110611fb857611fb86134f3565b9050602002016020810190611fcd91906134a3565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905561202981613551565b9050611ede565b5061203d60018484612d4c565b507ff263cfb3e4298332e776194610cf9fdc09ccb3ada8b9aa39764d882e11fbf0a08383336040516120719392919061378c565b60405180910390a1505050565b6120866123a8565b61208f81612bbf565b50565b61209a6123a8565b80806120a461297a565b1015612132576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f416d6f756e74207265717565737465642069732067726561746572207468616e60448201527f20776974686472617761626c652062616c616e6365000000000000000000000060648201526084016105ba565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af11580156121c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121eb91906136de565b61074e5761074e6137c6565b6121ff612353565b612265576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f742073657420617574686f72697a65642073656e6465727300000060448201526064016105ba565b7f1bb185903e2cb2f1b303523128b60e314dea81df4f8d9b7351cadd344f6e7727848484843360405161229c9594939291906137f5565b60405180910390a160005b83811015610968578484828181106122c1576122c16134f3565b90506020020160208101906122d691906134a3565b73ffffffffffffffffffffffffffffffffffffffff1663ee56997b84846040518363ffffffff1660e01b8152600401612310929190613845565b600060405180830381600087803b15801561232a57600080fd5b505af115801561233e573d6000803e3d6000fd5b505050508061234c90613551565b90506122a7565b3360009081526020819052604081205460ff168061104357503361238c60025473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b60025473ffffffffffffffffffffffffffffffffffffffff163314612429576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016105ba565b565b600080857f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036124e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f43616e6e6f742063616c6c20746f204c494e4b0000000000000000000000000060448201526064016105ba565b6040517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608b901b16602082015260348101869052605401604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291815281516020928301206000818152600490935291205490935060081b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016156125ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4d75737420757365206120756e6971756520494400000000000000000000000060448201526064016105ba565b6125fb61012c42613861565b6040805160208082018c90527fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608c901b16828401527fffffffff000000000000000000000000000000000000000000000000000000008a1660548301526058808301859052835180840390910181526078909201909252805191012090925060405180604001604052808260ff1916815260200161269a87612cb5565b60ff9081169091526000868152600460209081526040909120835193909101519091167f01000000000000000000000000000000000000000000000000000000000000000260089290921c9190911790556006546126f9908a90613861565b6006555050965096945050505050565b3360009081526020819052604090205460ff16612429576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f7420617574686f72697a65642073656e646572000000000000000000000060448201526064016105ba565b6040805160208082018890527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b16828401527fffffffff00000000000000000000000000000000000000000000000000000000861660548301526058808301869052835180840390910181526078909201909252805191012060009060008881526004602052604090205490915060081b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00908116908216146128a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f506172616d7320646f206e6f74206d617463682072657175657374204944000060448201526064016105ba565b6128af82612cb5565b60008881526004602052604090205460ff9182167f01000000000000000000000000000000000000000000000000000000000000009091049091161115612952576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f446174612076657273696f6e73206d757374206d61746368000000000000000060448201526064016105ba565b8560065461296091906136c5565b600655505050600093845250506004602052506040812055565b6000600160065461298b91906136c5565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015612a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a399190613874565b61104391906136c5565b612a4f6002602061388d565b612a5a906004613861565b81511015612ac4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f496e76616c69642072657175657374206c656e6774680000000000000000000060448201526064016105ba565b7fffffffff0000000000000000000000000000000000000000000000000000000082167f3c6d41b9000000000000000000000000000000000000000000000000000000001480612b5557507fffffffff0000000000000000000000000000000000000000000000000000000082167f4042994600000000000000000000000000000000000000000000000000000000145b612bbb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4d757374207573652077686974656c69737465642066756e6374696f6e73000060448201526064016105ba565b5050565b3373ffffffffffffffffffffffffffffffffffffffff821603612c3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016105ba565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217909255600254604051919216907fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae127890600090a350565b600060ff821115612d48576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203860448201527f206269747300000000000000000000000000000000000000000000000000000060648201526084016105ba565b5090565b828054828255906000526020600020908101928215612dc4579160200282015b82811115612dc45781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff843516178255602090920191600190910190612d6c565b50612d489291505b80821115612d485760008155600101612dcc565b60008083601f840112612df257600080fd5b50813567ffffffffffffffff811115612e0a57600080fd5b6020830191508360208260051b8501011115612e2557600080fd5b9250929050565b60008060208385031215612e3f57600080fd5b823567ffffffffffffffff811115612e5657600080fd5b612e6285828601612de0565b90969095509350505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461208f57600080fd5b60008083601f840112612ea257600080fd5b50813567ffffffffffffffff811115612eba57600080fd5b602083019150836020828501011115612e2557600080fd5b600080600060408486031215612ee757600080fd5b8335612ef281612e6e565b9250602084013567ffffffffffffffff811115612f0e57600080fd5b612f1a86828701612e90565b9497909650939450505050565b60005b83811015612f42578181015183820152602001612f2a565b50506000910152565b6020815260008251806020840152612f6a816040850160208701612f27565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6020808252825182820181905260009190848201906040850190845b81811015612fea57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612fb8565b50909695505050505050565b80357fffffffff000000000000000000000000000000000000000000000000000000008116811461302657600080fd5b919050565b60008060008060008060008060e0898b03121561304757600080fd5b883561305281612e6e565b9750602089013596506040890135955061306e60608a01612ff6565b94506080890135935060a0890135925060c089013567ffffffffffffffff81111561309857600080fd5b6130a48b828c01612e90565b999c989b5096995094979396929594505050565b6000806000604084860312156130cd57600080fd5b833567ffffffffffffffff8111156130e457600080fd5b6130f086828701612de0565b909450925050602084013561310481612e6e565b809150509250925092565b60008060008060008060008060006101008a8c03121561312e57600080fd5b893561313981612e6e565b985060208a0135975060408a0135965060608a013561315781612e6e565b955061316560808b01612ff6565b945060a08a0135935060c08a0135925060e08a013567ffffffffffffffff81111561318f57600080fd5b61319b8c828d01612e90565b915080935050809150509295985092959850929598565b60008060008060008060c087890312156131cb57600080fd5b863595506020870135945060408701356131e481612e6e565b93506131f260608801612ff6565b92506080870135915060a087013590509295509295509295565b6000806000806040858703121561322257600080fd5b843567ffffffffffffffff8082111561323a57600080fd5b61324688838901612de0565b9096509450602087013591508082111561325f57600080fd5b5061326c87828801612de0565b95989497509550505050565b600080600080600080600060c0888a03121561329357600080fd5b873596506020880135955060408801356132ac81612e6e565b94506132ba60608901612ff6565b93506080880135925060a088013567ffffffffffffffff8111156132dd57600080fd5b6132e98a828b01612e90565b989b979a50959850939692959293505050565b6000806000806080858703121561331257600080fd5b843593506020850135925061332960408601612ff6565b9396929550929360600135925050565b6000806000806060858703121561334f57600080fd5b843561335a81612e6e565b935060208501359250604085013567ffffffffffffffff81111561337d57600080fd5b61326c87828801612e90565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000606084860312156133cd57600080fd5b83356133d881612e6e565b925060208401359150604084013567ffffffffffffffff808211156133fc57600080fd5b818601915086601f83011261341057600080fd5b81358181111561342257613422613389565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561346857613468613389565b8160405282815289602084870101111561348157600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000602082840312156134b557600080fd5b81356134c081612e6e565b9392505050565b600080604083850312156134da57600080fd5b82356134e581612e6e565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361358257613582613522565b5060010190565b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600061010073ffffffffffffffffffffffffffffffffffffffff808d1684528b60208501528a6040850152808a166060850152507fffffffff00000000000000000000000000000000000000000000000000000000881660808401528660a08401528560c08401528060e084015261365d8184018587613599565b9c9b505050505050505050505050565b6000825161367f818460208701612f27565b9190910192915050565b7fffffffff0000000000000000000000000000000000000000000000000000000084168152818360048301376000910160040190815292915050565b818103818111156136d8576136d8613522565b92915050565b6000602082840312156136f057600080fd5b815180151581146134c057600080fd5b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152606060408201526000611b7e606083018486613599565b8183526000602080850194508260005b8581101561378157813561375981612e6e565b73ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101613746565b509495945050505050565b6040815260006137a0604083018587613736565b905073ffffffffffffffffffffffffffffffffffffffff83166020830152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b606081526000613809606083018789613736565b828103602084015261381c818688613736565b91505073ffffffffffffffffffffffffffffffffffffffff831660408301529695505050505050565b602081526000613859602083018486613736565b949350505050565b808201808211156136d8576136d8613522565b60006020828403121561388657600080fd5b5051919050565b80820281158282048414176136d8576136d861352256fea164736f6c6343000813000a", +} + +var OperatorABI = OperatorMetaData.ABI + +var OperatorBin = OperatorMetaData.Bin + +func DeployOperator(auth *bind.TransactOpts, backend bind.ContractBackend, link common.Address, owner common.Address) (common.Address, *types.Transaction, *Operator, error) { + parsed, err := OperatorMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(OperatorBin), backend, link, owner) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Operator{address: address, abi: *parsed, OperatorCaller: OperatorCaller{contract: contract}, OperatorTransactor: OperatorTransactor{contract: contract}, OperatorFilterer: OperatorFilterer{contract: contract}}, nil +} + +type Operator struct { + address common.Address + abi abi.ABI + OperatorCaller + OperatorTransactor + OperatorFilterer +} + +type OperatorCaller struct { + contract *bind.BoundContract +} + +type OperatorTransactor struct { + contract *bind.BoundContract +} + +type OperatorFilterer struct { + contract *bind.BoundContract +} + +type OperatorSession struct { + Contract *Operator + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type OperatorCallerSession struct { + Contract *OperatorCaller + CallOpts bind.CallOpts +} + +type OperatorTransactorSession struct { + Contract *OperatorTransactor + TransactOpts bind.TransactOpts +} + +type OperatorRaw struct { + Contract *Operator +} + +type OperatorCallerRaw struct { + Contract *OperatorCaller +} + +type OperatorTransactorRaw struct { + Contract *OperatorTransactor +} + +func NewOperator(address common.Address, backend bind.ContractBackend) (*Operator, error) { + abi, err := abi.JSON(strings.NewReader(OperatorABI)) + if err != nil { + return nil, err + } + contract, err := bindOperator(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Operator{address: address, abi: abi, OperatorCaller: OperatorCaller{contract: contract}, OperatorTransactor: OperatorTransactor{contract: contract}, OperatorFilterer: OperatorFilterer{contract: contract}}, nil +} + +func NewOperatorCaller(address common.Address, caller bind.ContractCaller) (*OperatorCaller, error) { + contract, err := bindOperator(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &OperatorCaller{contract: contract}, nil +} + +func NewOperatorTransactor(address common.Address, transactor bind.ContractTransactor) (*OperatorTransactor, error) { + contract, err := bindOperator(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &OperatorTransactor{contract: contract}, nil +} + +func NewOperatorFilterer(address common.Address, filterer bind.ContractFilterer) (*OperatorFilterer, error) { + contract, err := bindOperator(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &OperatorFilterer{contract: contract}, nil +} + +func bindOperator(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := OperatorMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_Operator *OperatorRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Operator.Contract.OperatorCaller.contract.Call(opts, result, method, params...) +} + +func (_Operator *OperatorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Operator.Contract.OperatorTransactor.contract.Transfer(opts) +} + +func (_Operator *OperatorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Operator.Contract.OperatorTransactor.contract.Transact(opts, method, params...) +} + +func (_Operator *OperatorCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Operator.Contract.contract.Call(opts, result, method, params...) +} + +func (_Operator *OperatorTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Operator.Contract.contract.Transfer(opts) +} + +func (_Operator *OperatorTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Operator.Contract.contract.Transact(opts, method, params...) +} + +func (_Operator *OperatorCaller) EXPIRYTIME(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Operator.contract.Call(opts, &out, "EXPIRYTIME") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_Operator *OperatorSession) EXPIRYTIME() (*big.Int, error) { + return _Operator.Contract.EXPIRYTIME(&_Operator.CallOpts) +} + +func (_Operator *OperatorCallerSession) EXPIRYTIME() (*big.Int, error) { + return _Operator.Contract.EXPIRYTIME(&_Operator.CallOpts) +} + +func (_Operator *OperatorCaller) GetAuthorizedSenders(opts *bind.CallOpts) ([]common.Address, error) { + var out []interface{} + err := _Operator.contract.Call(opts, &out, "getAuthorizedSenders") + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +func (_Operator *OperatorSession) GetAuthorizedSenders() ([]common.Address, error) { + return _Operator.Contract.GetAuthorizedSenders(&_Operator.CallOpts) +} + +func (_Operator *OperatorCallerSession) GetAuthorizedSenders() ([]common.Address, error) { + return _Operator.Contract.GetAuthorizedSenders(&_Operator.CallOpts) +} + +func (_Operator *OperatorCaller) GetChainlinkToken(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Operator.contract.Call(opts, &out, "getChainlinkToken") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_Operator *OperatorSession) GetChainlinkToken() (common.Address, error) { + return _Operator.Contract.GetChainlinkToken(&_Operator.CallOpts) +} + +func (_Operator *OperatorCallerSession) GetChainlinkToken() (common.Address, error) { + return _Operator.Contract.GetChainlinkToken(&_Operator.CallOpts) +} + +func (_Operator *OperatorCaller) IsAuthorizedSender(opts *bind.CallOpts, sender common.Address) (bool, error) { + var out []interface{} + err := _Operator.contract.Call(opts, &out, "isAuthorizedSender", sender) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_Operator *OperatorSession) IsAuthorizedSender(sender common.Address) (bool, error) { + return _Operator.Contract.IsAuthorizedSender(&_Operator.CallOpts, sender) +} + +func (_Operator *OperatorCallerSession) IsAuthorizedSender(sender common.Address) (bool, error) { + return _Operator.Contract.IsAuthorizedSender(&_Operator.CallOpts, sender) +} + +func (_Operator *OperatorCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Operator.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_Operator *OperatorSession) Owner() (common.Address, error) { + return _Operator.Contract.Owner(&_Operator.CallOpts) +} + +func (_Operator *OperatorCallerSession) Owner() (common.Address, error) { + return _Operator.Contract.Owner(&_Operator.CallOpts) +} + +func (_Operator *OperatorCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _Operator.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_Operator *OperatorSession) TypeAndVersion() (string, error) { + return _Operator.Contract.TypeAndVersion(&_Operator.CallOpts) +} + +func (_Operator *OperatorCallerSession) TypeAndVersion() (string, error) { + return _Operator.Contract.TypeAndVersion(&_Operator.CallOpts) +} + +func (_Operator *OperatorCaller) Withdrawable(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Operator.contract.Call(opts, &out, "withdrawable") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_Operator *OperatorSession) Withdrawable() (*big.Int, error) { + return _Operator.Contract.Withdrawable(&_Operator.CallOpts) +} + +func (_Operator *OperatorCallerSession) Withdrawable() (*big.Int, error) { + return _Operator.Contract.Withdrawable(&_Operator.CallOpts) +} + +func (_Operator *OperatorTransactor) AcceptAuthorizedReceivers(opts *bind.TransactOpts, targets []common.Address, senders []common.Address) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "acceptAuthorizedReceivers", targets, senders) +} + +func (_Operator *OperatorSession) AcceptAuthorizedReceivers(targets []common.Address, senders []common.Address) (*types.Transaction, error) { + return _Operator.Contract.AcceptAuthorizedReceivers(&_Operator.TransactOpts, targets, senders) +} + +func (_Operator *OperatorTransactorSession) AcceptAuthorizedReceivers(targets []common.Address, senders []common.Address) (*types.Transaction, error) { + return _Operator.Contract.AcceptAuthorizedReceivers(&_Operator.TransactOpts, targets, senders) +} + +func (_Operator *OperatorTransactor) AcceptOwnableContracts(opts *bind.TransactOpts, ownable []common.Address) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "acceptOwnableContracts", ownable) +} + +func (_Operator *OperatorSession) AcceptOwnableContracts(ownable []common.Address) (*types.Transaction, error) { + return _Operator.Contract.AcceptOwnableContracts(&_Operator.TransactOpts, ownable) +} + +func (_Operator *OperatorTransactorSession) AcceptOwnableContracts(ownable []common.Address) (*types.Transaction, error) { + return _Operator.Contract.AcceptOwnableContracts(&_Operator.TransactOpts, ownable) +} + +func (_Operator *OperatorTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "acceptOwnership") +} + +func (_Operator *OperatorSession) AcceptOwnership() (*types.Transaction, error) { + return _Operator.Contract.AcceptOwnership(&_Operator.TransactOpts) +} + +func (_Operator *OperatorTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _Operator.Contract.AcceptOwnership(&_Operator.TransactOpts) +} + +func (_Operator *OperatorTransactor) CancelOracleRequest(opts *bind.TransactOpts, requestId [32]byte, payment *big.Int, callbackFunc [4]byte, expiration *big.Int) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "cancelOracleRequest", requestId, payment, callbackFunc, expiration) +} + +func (_Operator *OperatorSession) CancelOracleRequest(requestId [32]byte, payment *big.Int, callbackFunc [4]byte, expiration *big.Int) (*types.Transaction, error) { + return _Operator.Contract.CancelOracleRequest(&_Operator.TransactOpts, requestId, payment, callbackFunc, expiration) +} + +func (_Operator *OperatorTransactorSession) CancelOracleRequest(requestId [32]byte, payment *big.Int, callbackFunc [4]byte, expiration *big.Int) (*types.Transaction, error) { + return _Operator.Contract.CancelOracleRequest(&_Operator.TransactOpts, requestId, payment, callbackFunc, expiration) +} + +func (_Operator *OperatorTransactor) CancelOracleRequestByRequester(opts *bind.TransactOpts, nonce *big.Int, payment *big.Int, callbackFunc [4]byte, expiration *big.Int) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "cancelOracleRequestByRequester", nonce, payment, callbackFunc, expiration) +} + +func (_Operator *OperatorSession) CancelOracleRequestByRequester(nonce *big.Int, payment *big.Int, callbackFunc [4]byte, expiration *big.Int) (*types.Transaction, error) { + return _Operator.Contract.CancelOracleRequestByRequester(&_Operator.TransactOpts, nonce, payment, callbackFunc, expiration) +} + +func (_Operator *OperatorTransactorSession) CancelOracleRequestByRequester(nonce *big.Int, payment *big.Int, callbackFunc [4]byte, expiration *big.Int) (*types.Transaction, error) { + return _Operator.Contract.CancelOracleRequestByRequester(&_Operator.TransactOpts, nonce, payment, callbackFunc, expiration) +} + +func (_Operator *OperatorTransactor) DistributeFunds(opts *bind.TransactOpts, receivers []common.Address, amounts []*big.Int) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "distributeFunds", receivers, amounts) +} + +func (_Operator *OperatorSession) DistributeFunds(receivers []common.Address, amounts []*big.Int) (*types.Transaction, error) { + return _Operator.Contract.DistributeFunds(&_Operator.TransactOpts, receivers, amounts) +} + +func (_Operator *OperatorTransactorSession) DistributeFunds(receivers []common.Address, amounts []*big.Int) (*types.Transaction, error) { + return _Operator.Contract.DistributeFunds(&_Operator.TransactOpts, receivers, amounts) +} + +func (_Operator *OperatorTransactor) FulfillOracleRequest(opts *bind.TransactOpts, requestId [32]byte, payment *big.Int, callbackAddress common.Address, callbackFunctionId [4]byte, expiration *big.Int, data [32]byte) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "fulfillOracleRequest", requestId, payment, callbackAddress, callbackFunctionId, expiration, data) +} + +func (_Operator *OperatorSession) FulfillOracleRequest(requestId [32]byte, payment *big.Int, callbackAddress common.Address, callbackFunctionId [4]byte, expiration *big.Int, data [32]byte) (*types.Transaction, error) { + return _Operator.Contract.FulfillOracleRequest(&_Operator.TransactOpts, requestId, payment, callbackAddress, callbackFunctionId, expiration, data) +} + +func (_Operator *OperatorTransactorSession) FulfillOracleRequest(requestId [32]byte, payment *big.Int, callbackAddress common.Address, callbackFunctionId [4]byte, expiration *big.Int, data [32]byte) (*types.Transaction, error) { + return _Operator.Contract.FulfillOracleRequest(&_Operator.TransactOpts, requestId, payment, callbackAddress, callbackFunctionId, expiration, data) +} + +func (_Operator *OperatorTransactor) FulfillOracleRequest2(opts *bind.TransactOpts, requestId [32]byte, payment *big.Int, callbackAddress common.Address, callbackFunctionId [4]byte, expiration *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "fulfillOracleRequest2", requestId, payment, callbackAddress, callbackFunctionId, expiration, data) +} + +func (_Operator *OperatorSession) FulfillOracleRequest2(requestId [32]byte, payment *big.Int, callbackAddress common.Address, callbackFunctionId [4]byte, expiration *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.Contract.FulfillOracleRequest2(&_Operator.TransactOpts, requestId, payment, callbackAddress, callbackFunctionId, expiration, data) +} + +func (_Operator *OperatorTransactorSession) FulfillOracleRequest2(requestId [32]byte, payment *big.Int, callbackAddress common.Address, callbackFunctionId [4]byte, expiration *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.Contract.FulfillOracleRequest2(&_Operator.TransactOpts, requestId, payment, callbackAddress, callbackFunctionId, expiration, data) +} + +func (_Operator *OperatorTransactor) OnTokenTransfer(opts *bind.TransactOpts, sender common.Address, amount *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "onTokenTransfer", sender, amount, data) +} + +func (_Operator *OperatorSession) OnTokenTransfer(sender common.Address, amount *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.Contract.OnTokenTransfer(&_Operator.TransactOpts, sender, amount, data) +} + +func (_Operator *OperatorTransactorSession) OnTokenTransfer(sender common.Address, amount *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.Contract.OnTokenTransfer(&_Operator.TransactOpts, sender, amount, data) +} + +func (_Operator *OperatorTransactor) OperatorRequest(opts *bind.TransactOpts, sender common.Address, payment *big.Int, specId [32]byte, callbackFunctionId [4]byte, nonce *big.Int, dataVersion *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "operatorRequest", sender, payment, specId, callbackFunctionId, nonce, dataVersion, data) +} + +func (_Operator *OperatorSession) OperatorRequest(sender common.Address, payment *big.Int, specId [32]byte, callbackFunctionId [4]byte, nonce *big.Int, dataVersion *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.Contract.OperatorRequest(&_Operator.TransactOpts, sender, payment, specId, callbackFunctionId, nonce, dataVersion, data) +} + +func (_Operator *OperatorTransactorSession) OperatorRequest(sender common.Address, payment *big.Int, specId [32]byte, callbackFunctionId [4]byte, nonce *big.Int, dataVersion *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.Contract.OperatorRequest(&_Operator.TransactOpts, sender, payment, specId, callbackFunctionId, nonce, dataVersion, data) +} + +func (_Operator *OperatorTransactor) OracleRequest(opts *bind.TransactOpts, sender common.Address, payment *big.Int, specId [32]byte, callbackAddress common.Address, callbackFunctionId [4]byte, nonce *big.Int, dataVersion *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "oracleRequest", sender, payment, specId, callbackAddress, callbackFunctionId, nonce, dataVersion, data) +} + +func (_Operator *OperatorSession) OracleRequest(sender common.Address, payment *big.Int, specId [32]byte, callbackAddress common.Address, callbackFunctionId [4]byte, nonce *big.Int, dataVersion *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.Contract.OracleRequest(&_Operator.TransactOpts, sender, payment, specId, callbackAddress, callbackFunctionId, nonce, dataVersion, data) +} + +func (_Operator *OperatorTransactorSession) OracleRequest(sender common.Address, payment *big.Int, specId [32]byte, callbackAddress common.Address, callbackFunctionId [4]byte, nonce *big.Int, dataVersion *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.Contract.OracleRequest(&_Operator.TransactOpts, sender, payment, specId, callbackAddress, callbackFunctionId, nonce, dataVersion, data) +} + +func (_Operator *OperatorTransactor) OwnerForward(opts *bind.TransactOpts, to common.Address, data []byte) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "ownerForward", to, data) +} + +func (_Operator *OperatorSession) OwnerForward(to common.Address, data []byte) (*types.Transaction, error) { + return _Operator.Contract.OwnerForward(&_Operator.TransactOpts, to, data) +} + +func (_Operator *OperatorTransactorSession) OwnerForward(to common.Address, data []byte) (*types.Transaction, error) { + return _Operator.Contract.OwnerForward(&_Operator.TransactOpts, to, data) +} + +func (_Operator *OperatorTransactor) OwnerTransferAndCall(opts *bind.TransactOpts, to common.Address, value *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "ownerTransferAndCall", to, value, data) +} + +func (_Operator *OperatorSession) OwnerTransferAndCall(to common.Address, value *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.Contract.OwnerTransferAndCall(&_Operator.TransactOpts, to, value, data) +} + +func (_Operator *OperatorTransactorSession) OwnerTransferAndCall(to common.Address, value *big.Int, data []byte) (*types.Transaction, error) { + return _Operator.Contract.OwnerTransferAndCall(&_Operator.TransactOpts, to, value, data) +} + +func (_Operator *OperatorTransactor) SetAuthorizedSenders(opts *bind.TransactOpts, senders []common.Address) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "setAuthorizedSenders", senders) +} + +func (_Operator *OperatorSession) SetAuthorizedSenders(senders []common.Address) (*types.Transaction, error) { + return _Operator.Contract.SetAuthorizedSenders(&_Operator.TransactOpts, senders) +} + +func (_Operator *OperatorTransactorSession) SetAuthorizedSenders(senders []common.Address) (*types.Transaction, error) { + return _Operator.Contract.SetAuthorizedSenders(&_Operator.TransactOpts, senders) +} + +func (_Operator *OperatorTransactor) SetAuthorizedSendersOn(opts *bind.TransactOpts, targets []common.Address, senders []common.Address) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "setAuthorizedSendersOn", targets, senders) +} + +func (_Operator *OperatorSession) SetAuthorizedSendersOn(targets []common.Address, senders []common.Address) (*types.Transaction, error) { + return _Operator.Contract.SetAuthorizedSendersOn(&_Operator.TransactOpts, targets, senders) +} + +func (_Operator *OperatorTransactorSession) SetAuthorizedSendersOn(targets []common.Address, senders []common.Address) (*types.Transaction, error) { + return _Operator.Contract.SetAuthorizedSendersOn(&_Operator.TransactOpts, targets, senders) +} + +func (_Operator *OperatorTransactor) TransferOwnableContracts(opts *bind.TransactOpts, ownable []common.Address, newOwner common.Address) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "transferOwnableContracts", ownable, newOwner) +} + +func (_Operator *OperatorSession) TransferOwnableContracts(ownable []common.Address, newOwner common.Address) (*types.Transaction, error) { + return _Operator.Contract.TransferOwnableContracts(&_Operator.TransactOpts, ownable, newOwner) +} + +func (_Operator *OperatorTransactorSession) TransferOwnableContracts(ownable []common.Address, newOwner common.Address) (*types.Transaction, error) { + return _Operator.Contract.TransferOwnableContracts(&_Operator.TransactOpts, ownable, newOwner) +} + +func (_Operator *OperatorTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "transferOwnership", to) +} + +func (_Operator *OperatorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _Operator.Contract.TransferOwnership(&_Operator.TransactOpts, to) +} + +func (_Operator *OperatorTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _Operator.Contract.TransferOwnership(&_Operator.TransactOpts, to) +} + +func (_Operator *OperatorTransactor) Withdraw(opts *bind.TransactOpts, recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _Operator.contract.Transact(opts, "withdraw", recipient, amount) +} + +func (_Operator *OperatorSession) Withdraw(recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _Operator.Contract.Withdraw(&_Operator.TransactOpts, recipient, amount) +} + +func (_Operator *OperatorTransactorSession) Withdraw(recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _Operator.Contract.Withdraw(&_Operator.TransactOpts, recipient, amount) +} + +type OperatorAuthorizedSendersChangedIterator struct { + Event *OperatorAuthorizedSendersChanged + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OperatorAuthorizedSendersChangedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OperatorAuthorizedSendersChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(OperatorAuthorizedSendersChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *OperatorAuthorizedSendersChangedIterator) Error() error { + return it.fail +} + +func (it *OperatorAuthorizedSendersChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OperatorAuthorizedSendersChanged struct { + Senders []common.Address + ChangedBy common.Address + Raw types.Log +} + +func (_Operator *OperatorFilterer) FilterAuthorizedSendersChanged(opts *bind.FilterOpts) (*OperatorAuthorizedSendersChangedIterator, error) { + + logs, sub, err := _Operator.contract.FilterLogs(opts, "AuthorizedSendersChanged") + if err != nil { + return nil, err + } + return &OperatorAuthorizedSendersChangedIterator{contract: _Operator.contract, event: "AuthorizedSendersChanged", logs: logs, sub: sub}, nil +} + +func (_Operator *OperatorFilterer) WatchAuthorizedSendersChanged(opts *bind.WatchOpts, sink chan<- *OperatorAuthorizedSendersChanged) (event.Subscription, error) { + + logs, sub, err := _Operator.contract.WatchLogs(opts, "AuthorizedSendersChanged") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OperatorAuthorizedSendersChanged) + if err := _Operator.contract.UnpackLog(event, "AuthorizedSendersChanged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_Operator *OperatorFilterer) ParseAuthorizedSendersChanged(log types.Log) (*OperatorAuthorizedSendersChanged, error) { + event := new(OperatorAuthorizedSendersChanged) + if err := _Operator.contract.UnpackLog(event, "AuthorizedSendersChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OperatorCancelOracleRequestIterator struct { + Event *OperatorCancelOracleRequest + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OperatorCancelOracleRequestIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OperatorCancelOracleRequest) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(OperatorCancelOracleRequest) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *OperatorCancelOracleRequestIterator) Error() error { + return it.fail +} + +func (it *OperatorCancelOracleRequestIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OperatorCancelOracleRequest struct { + RequestId [32]byte + Raw types.Log +} + +func (_Operator *OperatorFilterer) FilterCancelOracleRequest(opts *bind.FilterOpts, requestId [][32]byte) (*OperatorCancelOracleRequestIterator, error) { + + var requestIdRule []interface{} + for _, requestIdItem := range requestId { + requestIdRule = append(requestIdRule, requestIdItem) + } + + logs, sub, err := _Operator.contract.FilterLogs(opts, "CancelOracleRequest", requestIdRule) + if err != nil { + return nil, err + } + return &OperatorCancelOracleRequestIterator{contract: _Operator.contract, event: "CancelOracleRequest", logs: logs, sub: sub}, nil +} + +func (_Operator *OperatorFilterer) WatchCancelOracleRequest(opts *bind.WatchOpts, sink chan<- *OperatorCancelOracleRequest, requestId [][32]byte) (event.Subscription, error) { + + var requestIdRule []interface{} + for _, requestIdItem := range requestId { + requestIdRule = append(requestIdRule, requestIdItem) + } + + logs, sub, err := _Operator.contract.WatchLogs(opts, "CancelOracleRequest", requestIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OperatorCancelOracleRequest) + if err := _Operator.contract.UnpackLog(event, "CancelOracleRequest", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_Operator *OperatorFilterer) ParseCancelOracleRequest(log types.Log) (*OperatorCancelOracleRequest, error) { + event := new(OperatorCancelOracleRequest) + if err := _Operator.contract.UnpackLog(event, "CancelOracleRequest", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OperatorOracleRequestIterator struct { + Event *OperatorOracleRequest + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OperatorOracleRequestIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OperatorOracleRequest) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(OperatorOracleRequest) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *OperatorOracleRequestIterator) Error() error { + return it.fail +} + +func (it *OperatorOracleRequestIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OperatorOracleRequest struct { + SpecId [32]byte + Requester common.Address + RequestId [32]byte + Payment *big.Int + CallbackAddr common.Address + CallbackFunctionId [4]byte + CancelExpiration *big.Int + DataVersion *big.Int + Data []byte + Raw types.Log +} + +func (_Operator *OperatorFilterer) FilterOracleRequest(opts *bind.FilterOpts, specId [][32]byte) (*OperatorOracleRequestIterator, error) { + + var specIdRule []interface{} + for _, specIdItem := range specId { + specIdRule = append(specIdRule, specIdItem) + } + + logs, sub, err := _Operator.contract.FilterLogs(opts, "OracleRequest", specIdRule) + if err != nil { + return nil, err + } + return &OperatorOracleRequestIterator{contract: _Operator.contract, event: "OracleRequest", logs: logs, sub: sub}, nil +} + +func (_Operator *OperatorFilterer) WatchOracleRequest(opts *bind.WatchOpts, sink chan<- *OperatorOracleRequest, specId [][32]byte) (event.Subscription, error) { + + var specIdRule []interface{} + for _, specIdItem := range specId { + specIdRule = append(specIdRule, specIdItem) + } + + logs, sub, err := _Operator.contract.WatchLogs(opts, "OracleRequest", specIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OperatorOracleRequest) + if err := _Operator.contract.UnpackLog(event, "OracleRequest", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_Operator *OperatorFilterer) ParseOracleRequest(log types.Log) (*OperatorOracleRequest, error) { + event := new(OperatorOracleRequest) + if err := _Operator.contract.UnpackLog(event, "OracleRequest", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OperatorOracleResponseIterator struct { + Event *OperatorOracleResponse + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OperatorOracleResponseIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OperatorOracleResponse) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(OperatorOracleResponse) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *OperatorOracleResponseIterator) Error() error { + return it.fail +} + +func (it *OperatorOracleResponseIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OperatorOracleResponse struct { + RequestId [32]byte + Raw types.Log +} + +func (_Operator *OperatorFilterer) FilterOracleResponse(opts *bind.FilterOpts, requestId [][32]byte) (*OperatorOracleResponseIterator, error) { + + var requestIdRule []interface{} + for _, requestIdItem := range requestId { + requestIdRule = append(requestIdRule, requestIdItem) + } + + logs, sub, err := _Operator.contract.FilterLogs(opts, "OracleResponse", requestIdRule) + if err != nil { + return nil, err + } + return &OperatorOracleResponseIterator{contract: _Operator.contract, event: "OracleResponse", logs: logs, sub: sub}, nil +} + +func (_Operator *OperatorFilterer) WatchOracleResponse(opts *bind.WatchOpts, sink chan<- *OperatorOracleResponse, requestId [][32]byte) (event.Subscription, error) { + + var requestIdRule []interface{} + for _, requestIdItem := range requestId { + requestIdRule = append(requestIdRule, requestIdItem) + } + + logs, sub, err := _Operator.contract.WatchLogs(opts, "OracleResponse", requestIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OperatorOracleResponse) + if err := _Operator.contract.UnpackLog(event, "OracleResponse", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_Operator *OperatorFilterer) ParseOracleResponse(log types.Log) (*OperatorOracleResponse, error) { + event := new(OperatorOracleResponse) + if err := _Operator.contract.UnpackLog(event, "OracleResponse", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OperatorOwnableContractAcceptedIterator struct { + Event *OperatorOwnableContractAccepted + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OperatorOwnableContractAcceptedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OperatorOwnableContractAccepted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(OperatorOwnableContractAccepted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *OperatorOwnableContractAcceptedIterator) Error() error { + return it.fail +} + +func (it *OperatorOwnableContractAcceptedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OperatorOwnableContractAccepted struct { + AcceptedContract common.Address + Raw types.Log +} + +func (_Operator *OperatorFilterer) FilterOwnableContractAccepted(opts *bind.FilterOpts, acceptedContract []common.Address) (*OperatorOwnableContractAcceptedIterator, error) { + + var acceptedContractRule []interface{} + for _, acceptedContractItem := range acceptedContract { + acceptedContractRule = append(acceptedContractRule, acceptedContractItem) + } + + logs, sub, err := _Operator.contract.FilterLogs(opts, "OwnableContractAccepted", acceptedContractRule) + if err != nil { + return nil, err + } + return &OperatorOwnableContractAcceptedIterator{contract: _Operator.contract, event: "OwnableContractAccepted", logs: logs, sub: sub}, nil +} + +func (_Operator *OperatorFilterer) WatchOwnableContractAccepted(opts *bind.WatchOpts, sink chan<- *OperatorOwnableContractAccepted, acceptedContract []common.Address) (event.Subscription, error) { + + var acceptedContractRule []interface{} + for _, acceptedContractItem := range acceptedContract { + acceptedContractRule = append(acceptedContractRule, acceptedContractItem) + } + + logs, sub, err := _Operator.contract.WatchLogs(opts, "OwnableContractAccepted", acceptedContractRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OperatorOwnableContractAccepted) + if err := _Operator.contract.UnpackLog(event, "OwnableContractAccepted", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_Operator *OperatorFilterer) ParseOwnableContractAccepted(log types.Log) (*OperatorOwnableContractAccepted, error) { + event := new(OperatorOwnableContractAccepted) + if err := _Operator.contract.UnpackLog(event, "OwnableContractAccepted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OperatorOwnershipTransferRequestedIterator struct { + Event *OperatorOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OperatorOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OperatorOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(OperatorOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *OperatorOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *OperatorOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OperatorOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_Operator *OperatorFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OperatorOwnershipTransferRequestedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Operator.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &OperatorOwnershipTransferRequestedIterator{contract: _Operator.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_Operator *OperatorFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *OperatorOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Operator.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OperatorOwnershipTransferRequested) + if err := _Operator.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_Operator *OperatorFilterer) ParseOwnershipTransferRequested(log types.Log) (*OperatorOwnershipTransferRequested, error) { + event := new(OperatorOwnershipTransferRequested) + if err := _Operator.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OperatorOwnershipTransferredIterator struct { + Event *OperatorOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OperatorOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OperatorOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(OperatorOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *OperatorOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *OperatorOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OperatorOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_Operator *OperatorFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OperatorOwnershipTransferredIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Operator.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &OperatorOwnershipTransferredIterator{contract: _Operator.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_Operator *OperatorFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *OperatorOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Operator.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OperatorOwnershipTransferred) + if err := _Operator.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_Operator *OperatorFilterer) ParseOwnershipTransferred(log types.Log) (*OperatorOwnershipTransferred, error) { + event := new(OperatorOwnershipTransferred) + if err := _Operator.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OperatorTargetsUpdatedAuthorizedSendersIterator struct { + Event *OperatorTargetsUpdatedAuthorizedSenders + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OperatorTargetsUpdatedAuthorizedSendersIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OperatorTargetsUpdatedAuthorizedSenders) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(OperatorTargetsUpdatedAuthorizedSenders) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *OperatorTargetsUpdatedAuthorizedSendersIterator) Error() error { + return it.fail +} + +func (it *OperatorTargetsUpdatedAuthorizedSendersIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OperatorTargetsUpdatedAuthorizedSenders struct { + Targets []common.Address + Senders []common.Address + ChangedBy common.Address + Raw types.Log +} + +func (_Operator *OperatorFilterer) FilterTargetsUpdatedAuthorizedSenders(opts *bind.FilterOpts) (*OperatorTargetsUpdatedAuthorizedSendersIterator, error) { + + logs, sub, err := _Operator.contract.FilterLogs(opts, "TargetsUpdatedAuthorizedSenders") + if err != nil { + return nil, err + } + return &OperatorTargetsUpdatedAuthorizedSendersIterator{contract: _Operator.contract, event: "TargetsUpdatedAuthorizedSenders", logs: logs, sub: sub}, nil +} + +func (_Operator *OperatorFilterer) WatchTargetsUpdatedAuthorizedSenders(opts *bind.WatchOpts, sink chan<- *OperatorTargetsUpdatedAuthorizedSenders) (event.Subscription, error) { + + logs, sub, err := _Operator.contract.WatchLogs(opts, "TargetsUpdatedAuthorizedSenders") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OperatorTargetsUpdatedAuthorizedSenders) + if err := _Operator.contract.UnpackLog(event, "TargetsUpdatedAuthorizedSenders", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_Operator *OperatorFilterer) ParseTargetsUpdatedAuthorizedSenders(log types.Log) (*OperatorTargetsUpdatedAuthorizedSenders, error) { + event := new(OperatorTargetsUpdatedAuthorizedSenders) + if err := _Operator.contract.UnpackLog(event, "TargetsUpdatedAuthorizedSenders", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_Operator *Operator) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _Operator.abi.Events["AuthorizedSendersChanged"].ID: + return _Operator.ParseAuthorizedSendersChanged(log) + case _Operator.abi.Events["CancelOracleRequest"].ID: + return _Operator.ParseCancelOracleRequest(log) + case _Operator.abi.Events["OracleRequest"].ID: + return _Operator.ParseOracleRequest(log) + case _Operator.abi.Events["OracleResponse"].ID: + return _Operator.ParseOracleResponse(log) + case _Operator.abi.Events["OwnableContractAccepted"].ID: + return _Operator.ParseOwnableContractAccepted(log) + case _Operator.abi.Events["OwnershipTransferRequested"].ID: + return _Operator.ParseOwnershipTransferRequested(log) + case _Operator.abi.Events["OwnershipTransferred"].ID: + return _Operator.ParseOwnershipTransferred(log) + case _Operator.abi.Events["TargetsUpdatedAuthorizedSenders"].ID: + return _Operator.ParseTargetsUpdatedAuthorizedSenders(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (OperatorAuthorizedSendersChanged) Topic() common.Hash { + return common.HexToHash("0xf263cfb3e4298332e776194610cf9fdc09ccb3ada8b9aa39764d882e11fbf0a0") +} + +func (OperatorCancelOracleRequest) Topic() common.Hash { + return common.HexToHash("0xa7842b9ec549398102c0d91b1b9919b2f20558aefdadf57528a95c6cd3292e93") +} + +func (OperatorOracleRequest) Topic() common.Hash { + return common.HexToHash("0xd8d7ecc4800d25fa53ce0372f13a416d98907a7ef3d8d3bdd79cf4fe75529c65") +} + +func (OperatorOracleResponse) Topic() common.Hash { + return common.HexToHash("0x9e9bc7616d42c2835d05ae617e508454e63b30b934be8aa932ebc125e0e58a64") +} + +func (OperatorOwnableContractAccepted) Topic() common.Hash { + return common.HexToHash("0x615a0c1cb00a60d4acd77ec67acf2f17f223ef0932d591052fabc33643fe7e82") +} + +func (OperatorOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (OperatorOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (OperatorTargetsUpdatedAuthorizedSenders) Topic() common.Hash { + return common.HexToHash("0x1bb185903e2cb2f1b303523128b60e314dea81df4f8d9b7351cadd344f6e7727") +} + +func (_Operator *Operator) Address() common.Address { + return _Operator.address +} + +type OperatorInterface interface { + EXPIRYTIME(opts *bind.CallOpts) (*big.Int, error) + + GetAuthorizedSenders(opts *bind.CallOpts) ([]common.Address, error) + + GetChainlinkToken(opts *bind.CallOpts) (common.Address, error) + + IsAuthorizedSender(opts *bind.CallOpts, sender common.Address) (bool, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + Withdrawable(opts *bind.CallOpts) (*big.Int, error) + + AcceptAuthorizedReceivers(opts *bind.TransactOpts, targets []common.Address, senders []common.Address) (*types.Transaction, error) + + AcceptOwnableContracts(opts *bind.TransactOpts, ownable []common.Address) (*types.Transaction, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + CancelOracleRequest(opts *bind.TransactOpts, requestId [32]byte, payment *big.Int, callbackFunc [4]byte, expiration *big.Int) (*types.Transaction, error) + + CancelOracleRequestByRequester(opts *bind.TransactOpts, nonce *big.Int, payment *big.Int, callbackFunc [4]byte, expiration *big.Int) (*types.Transaction, error) + + DistributeFunds(opts *bind.TransactOpts, receivers []common.Address, amounts []*big.Int) (*types.Transaction, error) + + FulfillOracleRequest(opts *bind.TransactOpts, requestId [32]byte, payment *big.Int, callbackAddress common.Address, callbackFunctionId [4]byte, expiration *big.Int, data [32]byte) (*types.Transaction, error) + + FulfillOracleRequest2(opts *bind.TransactOpts, requestId [32]byte, payment *big.Int, callbackAddress common.Address, callbackFunctionId [4]byte, expiration *big.Int, data []byte) (*types.Transaction, error) + + OnTokenTransfer(opts *bind.TransactOpts, sender common.Address, amount *big.Int, data []byte) (*types.Transaction, error) + + OperatorRequest(opts *bind.TransactOpts, sender common.Address, payment *big.Int, specId [32]byte, callbackFunctionId [4]byte, nonce *big.Int, dataVersion *big.Int, data []byte) (*types.Transaction, error) + + OracleRequest(opts *bind.TransactOpts, sender common.Address, payment *big.Int, specId [32]byte, callbackAddress common.Address, callbackFunctionId [4]byte, nonce *big.Int, dataVersion *big.Int, data []byte) (*types.Transaction, error) + + OwnerForward(opts *bind.TransactOpts, to common.Address, data []byte) (*types.Transaction, error) + + OwnerTransferAndCall(opts *bind.TransactOpts, to common.Address, value *big.Int, data []byte) (*types.Transaction, error) + + SetAuthorizedSenders(opts *bind.TransactOpts, senders []common.Address) (*types.Transaction, error) + + SetAuthorizedSendersOn(opts *bind.TransactOpts, targets []common.Address, senders []common.Address) (*types.Transaction, error) + + TransferOwnableContracts(opts *bind.TransactOpts, ownable []common.Address, newOwner common.Address) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + Withdraw(opts *bind.TransactOpts, recipient common.Address, amount *big.Int) (*types.Transaction, error) + + FilterAuthorizedSendersChanged(opts *bind.FilterOpts) (*OperatorAuthorizedSendersChangedIterator, error) + + WatchAuthorizedSendersChanged(opts *bind.WatchOpts, sink chan<- *OperatorAuthorizedSendersChanged) (event.Subscription, error) + + ParseAuthorizedSendersChanged(log types.Log) (*OperatorAuthorizedSendersChanged, error) + + FilterCancelOracleRequest(opts *bind.FilterOpts, requestId [][32]byte) (*OperatorCancelOracleRequestIterator, error) + + WatchCancelOracleRequest(opts *bind.WatchOpts, sink chan<- *OperatorCancelOracleRequest, requestId [][32]byte) (event.Subscription, error) + + ParseCancelOracleRequest(log types.Log) (*OperatorCancelOracleRequest, error) + + FilterOracleRequest(opts *bind.FilterOpts, specId [][32]byte) (*OperatorOracleRequestIterator, error) + + WatchOracleRequest(opts *bind.WatchOpts, sink chan<- *OperatorOracleRequest, specId [][32]byte) (event.Subscription, error) + + ParseOracleRequest(log types.Log) (*OperatorOracleRequest, error) + + FilterOracleResponse(opts *bind.FilterOpts, requestId [][32]byte) (*OperatorOracleResponseIterator, error) + + WatchOracleResponse(opts *bind.WatchOpts, sink chan<- *OperatorOracleResponse, requestId [][32]byte) (event.Subscription, error) + + ParseOracleResponse(log types.Log) (*OperatorOracleResponse, error) + + FilterOwnableContractAccepted(opts *bind.FilterOpts, acceptedContract []common.Address) (*OperatorOwnableContractAcceptedIterator, error) + + WatchOwnableContractAccepted(opts *bind.WatchOpts, sink chan<- *OperatorOwnableContractAccepted, acceptedContract []common.Address) (event.Subscription, error) + + ParseOwnableContractAccepted(log types.Log) (*OperatorOwnableContractAccepted, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OperatorOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *OperatorOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*OperatorOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OperatorOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *OperatorOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*OperatorOwnershipTransferred, error) + + FilterTargetsUpdatedAuthorizedSenders(opts *bind.FilterOpts) (*OperatorTargetsUpdatedAuthorizedSendersIterator, error) + + WatchTargetsUpdatedAuthorizedSenders(opts *bind.WatchOpts, sink chan<- *OperatorTargetsUpdatedAuthorizedSenders) (event.Subscription, error) + + ParseTargetsUpdatedAuthorizedSenders(log types.Log) (*OperatorTargetsUpdatedAuthorizedSenders, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/operatorforwarder/generated/operator_factory/operator_factory.go b/core/gethwrappers/operatorforwarder/generated/operator_factory/operator_factory.go new file mode 100644 index 00000000000..4fc5e7448c5 --- /dev/null +++ b/core/gethwrappers/operatorforwarder/generated/operator_factory/operator_factory.go @@ -0,0 +1,632 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package operator_factory + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +var OperatorFactoryMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"linkAddress\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AuthorizedForwarderCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"OperatorCreated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"created\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployNewForwarder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"deployNewForwarderAndTransferOwnership\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployNewOperator\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deployNewOperatorAndForwarder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"linkToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60a060405234801561001057600080fd5b50604051615b16380380615b1683398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051615a686100ae6000396000818161014f015281816101e6015281816102e3015281816103da015281816104be01526105a50152615a686000f3fe60806040523480156200001157600080fd5b5060043610620000875760003560e01c806357970e93116200006257806357970e931462000149578063d42efd831462000171578063d689d09514620001be578063f4adb6e114620001d557600080fd5b8063181f5a77146200008c57806332f01eae14620000e15780633babafdb1462000119575b600080fd5b620000c96040518060400160405280601581526020017f4f70657261746f72466163746f727920312e302e30000000000000000000000081525081565b604051620000d8919062000717565b60405180910390f35b620000eb620001df565b6040805173ffffffffffffffffffffffffffffffffffffffff938416815292909116602083015201620000d8565b62000123620003c6565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620000d8565b620001237f000000000000000000000000000000000000000000000000000000000000000081565b620001ad620001823660046200075d565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205460ff1690565b6040519015158152602001620000d8565b62000123620001cf3660046200077b565b620004b9565b62000123620005a0565b60008060007f000000000000000000000000000000000000000000000000000000000000000033604051620002149062000695565b73ffffffffffffffffffffffffffffffffffffffff928316815291166020820152604001604051809103906000f08015801562000255573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff811660008181526020819052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555192935033928392917fd3bb727b2e716a1f142bc9c63c66fe0ae4c5fbc89234f8aa77d0c864a7b63bab91a4604080516000808252602082019092527f000000000000000000000000000000000000000000000000000000000000000090309084906040516200031590620006a3565b62000324949392919062000805565b604051809103906000f08015801562000341573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff811660008181526020819052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555192935033923092917f1c9576ab03e40fdf23673f82d904a0f029c8a6629272a4edad4be877e83af64b91a490939092509050565b6040805160008082526020820190925281907f000000000000000000000000000000000000000000000000000000000000000090339083906040516200040c90620006a3565b6200041b949392919062000805565b604051809103906000f08015801562000438573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff811660008181526020819052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555192935033928392917f1c9576ab03e40fdf23673f82d904a0f029c8a6629272a4edad4be877e83af64b91a4919050565b6000807f000000000000000000000000000000000000000000000000000000000000000033868686604051620004ef90620006a3565b620004ff95949392919062000852565b604051809103906000f0801580156200051c573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff811660008181526020819052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555192935033928392917f1c9576ab03e40fdf23673f82d904a0f029c8a6629272a4edad4be877e83af64b91a4949350505050565b6000807f000000000000000000000000000000000000000000000000000000000000000033604051620005d39062000695565b73ffffffffffffffffffffffffffffffffffffffff928316815291166020820152604001604051809103906000f08015801562000614573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff811660008181526020819052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555192935033928392917fd3bb727b2e716a1f142bc9c63c66fe0ae4c5fbc89234f8aa77d0c864a7b63bab91a4919050565b613aef80620008d483390190565b61169980620043c383390190565b6000815180845260005b81811015620006d957602081850181015186830182015201620006bb565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006200072c6020830184620006b1565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146200075857600080fd5b919050565b6000602082840312156200077057600080fd5b6200072c8262000733565b6000806000604084860312156200079157600080fd5b6200079c8462000733565b9250602084013567ffffffffffffffff80821115620007ba57600080fd5b818601915086601f830112620007cf57600080fd5b813581811115620007df57600080fd5b876020828501011115620007f257600080fd5b6020830194508093505050509250925092565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015280851660408401525060806060830152620008486080830184620006b1565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352808716602084015280861660408401525060806060830152826080830152828460a0840137600060a0848401015260a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8501168301019050969550505050505056fe60a060405260016006553480156200001657600080fd5b5060405162003aef38038062003aef8339810160408190526200003991620001ab565b808060006001600160a01b038216620000995760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600280546001600160a01b0319166001600160a01b0384811691909117909155811615620000cc57620000cc81620000e2565b505050506001600160a01b0316608052620001e3565b336001600160a01b038216036200013c5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000090565b600380546001600160a01b0319166001600160a01b03838116918217909255600254604051919216907fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae127890600090a350565b80516001600160a01b0381168114620001a657600080fd5b919050565b60008060408385031215620001bf57600080fd5b620001ca836200018e565b9150620001da602084016200018e565b90509250929050565b6080516138b16200023e600039600081816101ec0152818161075e015281816109f601528181610c520152818161189601528181611b0001528181611ba00152818161217e0152818161243101526129b901526138b16000f3fe6080604052600436106101965760003560e01c80636ae0bc76116100e1578063a4c0ed361161008a578063f2fde38b11610064578063f2fde38b146104aa578063f3fef3a3146104ca578063fa00763a146104ea578063fc4a03ed1461053057600080fd5b8063a4c0ed361461044a578063eb007d991461046a578063ee56997b1461048a57600080fd5b806379ba5097116100bb57806379ba5097146103ea5780638da5cb5b146103ff578063902fc3701461042a57600080fd5b80636ae0bc76146103975780636bd59ec0146103b75780636ee4d553146103ca57600080fd5b80633ec5bc1411610143578063501883011161011d578063501883011461033e57806352043783146103615780635ffa62881461037757600080fd5b80633ec5bc14146102ce57806340429946146102ee5780634ab0d1901461030e57600080fd5b8063181f5a7711610174578063181f5a77146102365780632408afaa1461028c5780633c6d41b9146102ae57600080fd5b806301994b991461019b578063033f49f7146101bd578063165d35e1146101dd575b600080fd5b3480156101a757600080fd5b506101bb6101b6366004612e2c565b610550565b005b3480156101c957600080fd5b506101bb6101d8366004612ed2565b610753565b3480156101e957600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561024257600080fd5b5061027f6040518060400160405280600e81526020017f4f70657261746f7220312e302e3000000000000000000000000000000000000081525081565b60405161022d9190612f4b565b34801561029857600080fd5b506102a161096f565b60405161022d9190612f9c565b3480156102ba57600080fd5b506101bb6102c936600461302b565b6109de565b3480156102da57600080fd5b506101bb6102e93660046130b8565b610ae6565b3480156102fa57600080fd5b506101bb61030936600461310f565b610c3a565b34801561031a57600080fd5b5061032e6103293660046131b2565b610d43565b604051901515815260200161022d565b34801561034a57600080fd5b50610353611039565b60405190815260200161022d565b34801561036d57600080fd5b5061035361012c81565b34801561038357600080fd5b506101bb61039236600461320c565b611048565b3480156103a357600080fd5b5061032e6103b2366004613278565b6110cc565b6101bb6103c536600461320c565b611448565b3480156103d657600080fd5b506101bb6103e53660046132fc565b611685565b3480156103f657600080fd5b506101bb611920565b34801561040b57600080fd5b5060025473ffffffffffffffffffffffffffffffffffffffff1661020c565b34801561043657600080fd5b5061032e610445366004613339565b611a21565b34801561045657600080fd5b506101bb6104653660046133b8565b611b88565b34801561047657600080fd5b506101bb6104853660046132fc565b611d16565b34801561049657600080fd5b506101bb6104a5366004612e2c565b611d70565b3480156104b657600080fd5b506101bb6104c53660046134a3565b61207e565b3480156104d657600080fd5b506101bb6104e53660046134c7565b612092565b3480156104f657600080fd5b5061032e6105053660046134a3565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205460ff1690565b34801561053c57600080fd5b506101bb61054b36600461320c565b6121f7565b610558612353565b6105c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f742073657420617574686f72697a65642073656e6465727300000060448201526064015b60405180910390fd5b60005b8181101561074e576001600560008585858181106105e6576105e66134f3565b90506020020160208101906105fb91906134a3565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055828282818110610660576106606134f3565b905060200201602081019061067591906134a3565b73ffffffffffffffffffffffffffffffffffffffff167f615a0c1cb00a60d4acd77ec67acf2f17f223ef0932d591052fabc33643fe7e8260405160405180910390a28282828181106106c9576106c96134f3565b90506020020160208101906106de91906134a3565b73ffffffffffffffffffffffffffffffffffffffff166379ba50976040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561072557600080fd5b505af1158015610739573d6000803e3d6000fd5b505050508061074790613551565b90506105c6565b505050565b61075b6123a8565b827f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610811576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f43616e6e6f742063616c6c20746f204c494e4b0000000000000000000000000060448201526064016105ba565b8373ffffffffffffffffffffffffffffffffffffffff163b600003610892576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d75737420666f727761726420746f206120636f6e747261637400000000000060448201526064016105ba565b60008473ffffffffffffffffffffffffffffffffffffffff1684846040516108bb929190613589565b6000604051808303816000865af19150503d80600081146108f8576040519150601f19603f3d011682016040523d82523d6000602084013e6108fd565b606091505b5050905080610968576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f466f727761726465642063616c6c206661696c6564000000000000000000000060448201526064016105ba565b5050505050565b606060018054806020026020016040519081016040528092919081815260200182805480156109d457602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116109a9575b5050505050905090565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610a7d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d75737420757365204c494e4b20746f6b656e0000000000000000000000000060448201526064016105ba565b600080610a8e8a8a8c8a8a8a61242b565b91509150877fd8d7ecc4800d25fa53ce0372f13a416d98907a7ef3d8d3bdd79cf4fe75529c658b848c8e8c878c8c8c604051610ad2999897969594939291906135e2565b60405180910390a250505050505050505050565b610aee6123a8565b60005b82811015610c3457600060056000868685818110610b1157610b116134f3565b9050602002016020810190610b2691906134a3565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055838382818110610b8b57610b8b6134f3565b9050602002016020810190610ba091906134a3565b6040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152919091169063f2fde38b90602401600060405180830381600087803b158015610c0b57600080fd5b505af1158015610c1f573d6000803e3d6000fd5b5050505080610c2d90613551565b9050610af1565b50505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610cd9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d75737420757365204c494e4b20746f6b656e0000000000000000000000000060448201526064016105ba565b600080610cea8b8b8a8a8a8a61242b565b91509150887fd8d7ecc4800d25fa53ce0372f13a416d98907a7ef3d8d3bdd79cf4fe75529c658c848d8f8c878c8c8c604051610d2e999897969594939291906135e2565b60405180910390a25050505050505050505050565b6000610d4d612709565b600087815260046020526040812054889160089190911b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169003610dee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4d757374206861766520612076616c696420726571756573744964000000000060448201526064016105ba565b73ffffffffffffffffffffffffffffffffffffffff8616600090815260056020526040902054869060ff1615610e80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f43616e6e6f742063616c6c206f776e656420636f6e747261637400000000000060448201526064016105ba565b610e8f89898989896001612782565b60405189907f9e9bc7616d42c2835d05ae617e508454e63b30b934be8aa932ebc125e0e58a6490600090a262061a805a1015610f27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4d7573742070726f7669646520636f6e73756d657220656e6f7567682067617360448201526064016105ba565b60008773ffffffffffffffffffffffffffffffffffffffff16878b87604051602401610f5d929190918252602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051610fe6919061366d565b6000604051808303816000865af19150503d8060008114611023576040519150601f19603f3d011682016040523d82523d6000602084013e611028565b606091505b50909b9a5050505050505050505050565b600061104361297a565b905090565b611050612353565b6110b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f742073657420617574686f72697a65642073656e6465727300000060448201526064016105ba565b6110c08484610550565b610c34848484846121f7565b60006110d6612709565b600088815260046020526040812054899160089190911b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169003611177576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4d757374206861766520612076616c696420726571756573744964000000000060448201526064016105ba565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260056020526040902054879060ff1615611209576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f43616e6e6f742063616c6c206f776e656420636f6e747261637400000000000060448201526064016105ba565b8985856020811015611277576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f526573706f6e7365206d757374206265203e203332206279746573000000000060448201526064016105ba565b81358381146112e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f466972737420776f7264206d757374206265207265717565737449640000000060448201526064016105ba565b6112f18e8e8e8e8e6002612782565b6040518e907f9e9bc7616d42c2835d05ae617e508454e63b30b934be8aa932ebc125e0e58a6490600090a262061a805a1015611389576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4d7573742070726f7669646520636f6e73756d657220656e6f7567682067617360448201526064016105ba565b60008c73ffffffffffffffffffffffffffffffffffffffff168c8b8b6040516020016113b793929190613689565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526113ef9161366d565b6000604051808303816000865af19150503d806000811461142c576040519150601f19603f3d011682016040523d82523d6000602084013e611431565b606091505b509098505050505050505050979650505050505050565b821580159061145657508281145b6114bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c6964206172726179206c656e67746828732900000000000000000060448201526064016105ba565b3460005b8481101561161c5760008484838181106114dc576114dc6134f3565b90506020020135905080836114f191906136c5565b92506000878784818110611507576115076134f3565b905060200201602081019061151c91906134a3565b73ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611573576040519150601f19603f3d011682016040523d82523d6000602084013e611578565b606091505b5050905080611609576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016105ba565b50508061161590613551565b90506114c0565b508015610968576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f546f6f206d756368204554482073656e7400000000000000000000000000000060448201526064016105ba565b6040805160208082018690527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b16828401527fffffffff00000000000000000000000000000000000000000000000000000000851660548301526058808301859052835180840390910181526078909201909252805191012060009060008681526004602052604090205490915060081b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00908116908216146117a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f506172616d7320646f206e6f74206d617463682072657175657374204944000060448201526064016105ba565b42821115611812576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f52657175657374206973206e6f7420657870697265640000000000000000000060448201526064016105ba565b6000858152600460205260408082208290555186917fa7842b9ec549398102c0d91b1b9919b2f20558aefdadf57528a95c6cd3292e9391a2836006600082825461185c91906136c5565b90915550506040517fa9059cbb000000000000000000000000000000000000000000000000000000008152336004820152602481018590527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a9059cbb906044016020604051808303816000875af11580156118f4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191891906136de565b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633146119a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016105ba565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560038054909116905560405173ffffffffffffffffffffffffffffffffffffffff909116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a350565b6000611a2b6123a8565b8380611a3561297a565b1015611ac3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f416d6f756e74207265717565737465642069732067726561746572207468616e60448201527f20776974686472617761626c652062616c616e6365000000000000000000000060648201526084016105ba565b6040517f4000aea000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690634000aea090611b3b908990899089908990600401613700565b6020604051808303816000875af1158015611b5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b7e91906136de565b9695505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614611c27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4d75737420757365204c494e4b20746f6b656e0000000000000000000000000060448201526064016105ba565b60208101518190611c388183612a43565b84602484015283604484015260003073ffffffffffffffffffffffffffffffffffffffff1684604051611c6b919061366d565b600060405180830381855af49150503d8060008114611ca6576040519150601f19603f3d011682016040523d82523d6000602084013e611cab565b606091505b5050905080611918576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f556e61626c6520746f206372656174652072657175657374000000000000000060448201526064016105ba565b6040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b16602082015260348101859052610c349060540160405160208183030381529060405280519060200120848484611685565b611d78612353565b611dde576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f742073657420617574686f72697a65642073656e6465727300000060448201526064016105ba565b80611e45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4d7573742068617665206174206c6561737420312073656e646572000000000060448201526064016105ba565b60015460005b81811015611eda57600080600060018481548110611e6b57611e6b6134f3565b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055611ed381613551565b9050611e4b565b5060005b8281101561203057600080858584818110611efb57611efb6134f3565b9050602002016020810190611f1091906134a3565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000205460ff1615611fa1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4d757374206e6f742068617665206475706c69636174652073656e646572730060448201526064016105ba565b6001600080868685818110611fb857611fb86134f3565b9050602002016020810190611fcd91906134a3565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905561202981613551565b9050611ede565b5061203d60018484612d4c565b507ff263cfb3e4298332e776194610cf9fdc09ccb3ada8b9aa39764d882e11fbf0a08383336040516120719392919061378c565b60405180910390a1505050565b6120866123a8565b61208f81612bbf565b50565b61209a6123a8565b80806120a461297a565b1015612132576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f416d6f756e74207265717565737465642069732067726561746572207468616e60448201527f20776974686472617761626c652062616c616e6365000000000000000000000060648201526084016105ba565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af11580156121c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121eb91906136de565b61074e5761074e6137c6565b6121ff612353565b612265576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f742073657420617574686f72697a65642073656e6465727300000060448201526064016105ba565b7f1bb185903e2cb2f1b303523128b60e314dea81df4f8d9b7351cadd344f6e7727848484843360405161229c9594939291906137f5565b60405180910390a160005b83811015610968578484828181106122c1576122c16134f3565b90506020020160208101906122d691906134a3565b73ffffffffffffffffffffffffffffffffffffffff1663ee56997b84846040518363ffffffff1660e01b8152600401612310929190613845565b600060405180830381600087803b15801561232a57600080fd5b505af115801561233e573d6000803e3d6000fd5b505050508061234c90613551565b90506122a7565b3360009081526020819052604081205460ff168061104357503361238c60025473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b60025473ffffffffffffffffffffffffffffffffffffffff163314612429576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016105ba565b565b600080857f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036124e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f43616e6e6f742063616c6c20746f204c494e4b0000000000000000000000000060448201526064016105ba565b6040517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608b901b16602082015260348101869052605401604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291815281516020928301206000818152600490935291205490935060081b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016156125ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4d75737420757365206120756e6971756520494400000000000000000000000060448201526064016105ba565b6125fb61012c42613861565b6040805160208082018c90527fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608c901b16828401527fffffffff000000000000000000000000000000000000000000000000000000008a1660548301526058808301859052835180840390910181526078909201909252805191012090925060405180604001604052808260ff1916815260200161269a87612cb5565b60ff9081169091526000868152600460209081526040909120835193909101519091167f01000000000000000000000000000000000000000000000000000000000000000260089290921c9190911790556006546126f9908a90613861565b6006555050965096945050505050565b3360009081526020819052604090205460ff16612429576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f7420617574686f72697a65642073656e646572000000000000000000000060448201526064016105ba565b6040805160208082018890527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b16828401527fffffffff00000000000000000000000000000000000000000000000000000000861660548301526058808301869052835180840390910181526078909201909252805191012060009060008881526004602052604090205490915060081b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00908116908216146128a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f506172616d7320646f206e6f74206d617463682072657175657374204944000060448201526064016105ba565b6128af82612cb5565b60008881526004602052604090205460ff9182167f01000000000000000000000000000000000000000000000000000000000000009091049091161115612952576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f446174612076657273696f6e73206d757374206d61746368000000000000000060448201526064016105ba565b8560065461296091906136c5565b600655505050600093845250506004602052506040812055565b6000600160065461298b91906136c5565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015612a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a399190613874565b61104391906136c5565b612a4f6002602061388d565b612a5a906004613861565b81511015612ac4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f496e76616c69642072657175657374206c656e6774680000000000000000000060448201526064016105ba565b7fffffffff0000000000000000000000000000000000000000000000000000000082167f3c6d41b9000000000000000000000000000000000000000000000000000000001480612b5557507fffffffff0000000000000000000000000000000000000000000000000000000082167f4042994600000000000000000000000000000000000000000000000000000000145b612bbb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4d757374207573652077686974656c69737465642066756e6374696f6e73000060448201526064016105ba565b5050565b3373ffffffffffffffffffffffffffffffffffffffff821603612c3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016105ba565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217909255600254604051919216907fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae127890600090a350565b600060ff821115612d48576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203860448201527f206269747300000000000000000000000000000000000000000000000000000060648201526084016105ba565b5090565b828054828255906000526020600020908101928215612dc4579160200282015b82811115612dc45781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff843516178255602090920191600190910190612d6c565b50612d489291505b80821115612d485760008155600101612dcc565b60008083601f840112612df257600080fd5b50813567ffffffffffffffff811115612e0a57600080fd5b6020830191508360208260051b8501011115612e2557600080fd5b9250929050565b60008060208385031215612e3f57600080fd5b823567ffffffffffffffff811115612e5657600080fd5b612e6285828601612de0565b90969095509350505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461208f57600080fd5b60008083601f840112612ea257600080fd5b50813567ffffffffffffffff811115612eba57600080fd5b602083019150836020828501011115612e2557600080fd5b600080600060408486031215612ee757600080fd5b8335612ef281612e6e565b9250602084013567ffffffffffffffff811115612f0e57600080fd5b612f1a86828701612e90565b9497909650939450505050565b60005b83811015612f42578181015183820152602001612f2a565b50506000910152565b6020815260008251806020840152612f6a816040850160208701612f27565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6020808252825182820181905260009190848201906040850190845b81811015612fea57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612fb8565b50909695505050505050565b80357fffffffff000000000000000000000000000000000000000000000000000000008116811461302657600080fd5b919050565b60008060008060008060008060e0898b03121561304757600080fd5b883561305281612e6e565b9750602089013596506040890135955061306e60608a01612ff6565b94506080890135935060a0890135925060c089013567ffffffffffffffff81111561309857600080fd5b6130a48b828c01612e90565b999c989b5096995094979396929594505050565b6000806000604084860312156130cd57600080fd5b833567ffffffffffffffff8111156130e457600080fd5b6130f086828701612de0565b909450925050602084013561310481612e6e565b809150509250925092565b60008060008060008060008060006101008a8c03121561312e57600080fd5b893561313981612e6e565b985060208a0135975060408a0135965060608a013561315781612e6e565b955061316560808b01612ff6565b945060a08a0135935060c08a0135925060e08a013567ffffffffffffffff81111561318f57600080fd5b61319b8c828d01612e90565b915080935050809150509295985092959850929598565b60008060008060008060c087890312156131cb57600080fd5b863595506020870135945060408701356131e481612e6e565b93506131f260608801612ff6565b92506080870135915060a087013590509295509295509295565b6000806000806040858703121561322257600080fd5b843567ffffffffffffffff8082111561323a57600080fd5b61324688838901612de0565b9096509450602087013591508082111561325f57600080fd5b5061326c87828801612de0565b95989497509550505050565b600080600080600080600060c0888a03121561329357600080fd5b873596506020880135955060408801356132ac81612e6e565b94506132ba60608901612ff6565b93506080880135925060a088013567ffffffffffffffff8111156132dd57600080fd5b6132e98a828b01612e90565b989b979a50959850939692959293505050565b6000806000806080858703121561331257600080fd5b843593506020850135925061332960408601612ff6565b9396929550929360600135925050565b6000806000806060858703121561334f57600080fd5b843561335a81612e6e565b935060208501359250604085013567ffffffffffffffff81111561337d57600080fd5b61326c87828801612e90565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000606084860312156133cd57600080fd5b83356133d881612e6e565b925060208401359150604084013567ffffffffffffffff808211156133fc57600080fd5b818601915086601f83011261341057600080fd5b81358181111561342257613422613389565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561346857613468613389565b8160405282815289602084870101111561348157600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000602082840312156134b557600080fd5b81356134c081612e6e565b9392505050565b600080604083850312156134da57600080fd5b82356134e581612e6e565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361358257613582613522565b5060010190565b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600061010073ffffffffffffffffffffffffffffffffffffffff808d1684528b60208501528a6040850152808a166060850152507fffffffff00000000000000000000000000000000000000000000000000000000881660808401528660a08401528560c08401528060e084015261365d8184018587613599565b9c9b505050505050505050505050565b6000825161367f818460208701612f27565b9190910192915050565b7fffffffff0000000000000000000000000000000000000000000000000000000084168152818360048301376000910160040190815292915050565b818103818111156136d8576136d8613522565b92915050565b6000602082840312156136f057600080fd5b815180151581146134c057600080fd5b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152606060408201526000611b7e606083018486613599565b8183526000602080850194508260005b8581101561378157813561375981612e6e565b73ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101613746565b509495945050505050565b6040815260006137a0604083018587613736565b905073ffffffffffffffffffffffffffffffffffffffff83166020830152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b606081526000613809606083018789613736565b828103602084015261381c818688613736565b91505073ffffffffffffffffffffffffffffffffffffffff831660408301529695505050505050565b602081526000613859602083018486613736565b949350505050565b808201808211156136d8576136d8613522565b60006020828403121561388657600080fd5b5051919050565b80820281158282048414176136d8576136d861352256fea164736f6c6343000813000a60a06040523480156200001157600080fd5b50604051620016993803806200169983398101604081905262000034916200029d565b82826001600160a01b038216620000925760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c557620000c58162000199565b50506001600160a01b0384166200012b5760405162461bcd60e51b815260206004820152602360248201527f4c696e6b20746f6b656e2063616e6e6f742062652061207a65726f206164647260448201526265737360e81b606482015260840162000089565b6001600160a01b038085166080528216156200018f57816001600160a01b0316836001600160a01b03167f4e1e878dc28d5f040db5969163ff1acd75c44c3f655da2dde9c70bbd8e56dc7e836040516200018691906200038e565b60405180910390a35b50505050620003c3565b336001600160a01b03821603620001f35760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000089565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b03811681146200025c57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620002945781810151838201526020016200027a565b50506000910152565b60008060008060808587031215620002b457600080fd5b620002bf8562000244565b9350620002cf6020860162000244565b9250620002df6040860162000244565b60608601519092506001600160401b0380821115620002fd57600080fd5b818701915087601f8301126200031257600080fd5b81518181111562000327576200032762000261565b604051601f8201601f19908116603f0116810190838211818310171562000352576200035262000261565b816040528281528a60208487010111156200036c57600080fd5b6200037f83602083016020880162000277565b979a9699509497505050505050565b6020815260008251806020840152620003af81604085016020870162000277565b601f01601f19169190910160400192915050565b6080516112ac620003ed6000396000818161016d0152818161037501526105d301526112ac6000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c806379ba509711610081578063ee56997b1161005b578063ee56997b14610200578063f2fde38b14610213578063fa00763a1461022657600080fd5b806379ba5097146101c75780638da5cb5b146101cf578063b64fa9e6146101ed57600080fd5b80634d3e2323116100b25780634d3e23231461015557806357970e93146101685780636fadcf72146101b457600080fd5b8063033f49f7146100d9578063181f5a77146100ee5780632408afaa14610140575b600080fd5b6100ec6100e7366004610e72565b61026f565b005b61012a6040518060400160405280601981526020017f417574686f72697a6564466f7277617264657220312e312e300000000000000081525081565b6040516101379190610ef5565b60405180910390f35b610148610287565b6040516101379190610f61565b6100ec610163366004610e72565b6102f6565b61018f7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610137565b6100ec6101c2366004610e72565b61036b565b6100ec61042d565b60005473ffffffffffffffffffffffffffffffffffffffff1661018f565b6100ec6101fb366004611007565b61052a565b6100ec61020e366004611073565b6106cb565b6100ec6102213660046110b5565b6109dc565b61025f6102343660046110b5565b73ffffffffffffffffffffffffffffffffffffffff1660009081526002602052604090205460ff1690565b6040519015158152602001610137565b6102776109f0565b610282838383610a73565b505050565b606060038054806020026020016040519081016040528092919081815260200182805480156102ec57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116102c1575b5050505050905090565b6102ff836109dc565b8273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f4e1e878dc28d5f040db5969163ff1acd75c44c3f655da2dde9c70bbd8e56dc7e848460405161035e9291906110d7565b60405180910390a3505050565b610373610c00565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610277576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43616e6e6f7420666f727761726420746f204c696e6b20746f6b656e0000000060448201526064015b60405180910390fd5b60015473ffffffffffffffffffffffffffffffffffffffff1633146104ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610424565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610532610c00565b82811461059b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f417272617973206d7573742068617665207468652073616d65206c656e6774686044820152606401610424565b60005b838110156106c45760008585838181106105ba576105ba611124565b90506020020160208101906105cf91906110b5565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610686576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43616e6e6f7420666f727761726420746f204c696e6b20746f6b656e000000006044820152606401610424565b6106b38185858581811061069c5761069c611124565b90506020028101906106ae9190611153565b610a73565b506106bd816111b8565b905061059e565b5050505050565b6106d3610c79565b610739576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f43616e6e6f742073657420617574686f72697a65642073656e646572730000006044820152606401610424565b806107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4d7573742068617665206174206c6561737420312073656e64657200000000006044820152606401610424565b60035460005b8181101561083657600060026000600384815481106107c7576107c7611124565b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905561082f816111b8565b90506107a6565b5060005b8281101561098e576002600085858481811061085857610858611124565b905060200201602081019061086d91906110b5565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000205460ff16156108fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4d757374206e6f742068617665206475706c69636174652073656e64657273006044820152606401610424565b60016002600086868581811061091657610916611124565b905060200201602081019061092b91906110b5565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055610987816111b8565b905061083a565b5061099b60038484610dac565b507ff263cfb3e4298332e776194610cf9fdc09ccb3ada8b9aa39764d882e11fbf0a08383336040516109cf93929190611217565b60405180910390a1505050565b6109e46109f0565b6109ed81610cb7565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610424565b565b73ffffffffffffffffffffffffffffffffffffffff83163b610af1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d75737420666f727761726420746f206120636f6e74726163740000000000006044820152606401610424565b6000808473ffffffffffffffffffffffffffffffffffffffff168484604051610b1b92919061128f565b6000604051808303816000865af19150503d8060008114610b58576040519150601f19603f3d011682016040523d82523d6000602084013e610b5d565b606091505b5091509150816106c4578051600003610bf8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f466f727761726465642063616c6c20726576657274656420776974686f75742060448201527f726561736f6e00000000000000000000000000000000000000000000000000006064820152608401610424565b805181602001fd5b3360009081526002602052604090205460ff16610a71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f7420617574686f72697a65642073656e64657200000000000000000000006044820152606401610424565b600033610c9b60005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b3373ffffffffffffffffffffffffffffffffffffffff821603610d36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610424565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b828054828255906000526020600020908101928215610e24579160200282015b82811115610e245781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff843516178255602090920191600190910190610dcc565b50610e30929150610e34565b5090565b5b80821115610e305760008155600101610e35565b803573ffffffffffffffffffffffffffffffffffffffff81168114610e6d57600080fd5b919050565b600080600060408486031215610e8757600080fd5b610e9084610e49565b9250602084013567ffffffffffffffff80821115610ead57600080fd5b818601915086601f830112610ec157600080fd5b813581811115610ed057600080fd5b876020828501011115610ee257600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b81811015610f2257858101830151858201604001528201610f06565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6020808252825182820181905260009190848201906040850190845b81811015610faf57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101610f7d565b50909695505050505050565b60008083601f840112610fcd57600080fd5b50813567ffffffffffffffff811115610fe557600080fd5b6020830191508360208260051b850101111561100057600080fd5b9250929050565b6000806000806040858703121561101d57600080fd5b843567ffffffffffffffff8082111561103557600080fd5b61104188838901610fbb565b9096509450602087013591508082111561105a57600080fd5b5061106787828801610fbb565b95989497509550505050565b6000806020838503121561108657600080fd5b823567ffffffffffffffff81111561109d57600080fd5b6110a985828601610fbb565b90969095509350505050565b6000602082840312156110c757600080fd5b6110d082610e49565b9392505050565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261118857600080fd5b83018035915067ffffffffffffffff8211156111a357600080fd5b60200191503681900382131561100057600080fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611210577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b6040808252810183905260008460608301825b868110156112655773ffffffffffffffffffffffffffffffffffffffff61125084610e49565b1682526020928301929091019060010161122a565b50809250505073ffffffffffffffffffffffffffffffffffffffff83166020830152949350505050565b818382376000910190815291905056fea164736f6c6343000813000aa164736f6c6343000813000a", +} + +var OperatorFactoryABI = OperatorFactoryMetaData.ABI + +var OperatorFactoryBin = OperatorFactoryMetaData.Bin + +func DeployOperatorFactory(auth *bind.TransactOpts, backend bind.ContractBackend, linkAddress common.Address) (common.Address, *types.Transaction, *OperatorFactory, error) { + parsed, err := OperatorFactoryMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(OperatorFactoryBin), backend, linkAddress) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &OperatorFactory{address: address, abi: *parsed, OperatorFactoryCaller: OperatorFactoryCaller{contract: contract}, OperatorFactoryTransactor: OperatorFactoryTransactor{contract: contract}, OperatorFactoryFilterer: OperatorFactoryFilterer{contract: contract}}, nil +} + +type OperatorFactory struct { + address common.Address + abi abi.ABI + OperatorFactoryCaller + OperatorFactoryTransactor + OperatorFactoryFilterer +} + +type OperatorFactoryCaller struct { + contract *bind.BoundContract +} + +type OperatorFactoryTransactor struct { + contract *bind.BoundContract +} + +type OperatorFactoryFilterer struct { + contract *bind.BoundContract +} + +type OperatorFactorySession struct { + Contract *OperatorFactory + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type OperatorFactoryCallerSession struct { + Contract *OperatorFactoryCaller + CallOpts bind.CallOpts +} + +type OperatorFactoryTransactorSession struct { + Contract *OperatorFactoryTransactor + TransactOpts bind.TransactOpts +} + +type OperatorFactoryRaw struct { + Contract *OperatorFactory +} + +type OperatorFactoryCallerRaw struct { + Contract *OperatorFactoryCaller +} + +type OperatorFactoryTransactorRaw struct { + Contract *OperatorFactoryTransactor +} + +func NewOperatorFactory(address common.Address, backend bind.ContractBackend) (*OperatorFactory, error) { + abi, err := abi.JSON(strings.NewReader(OperatorFactoryABI)) + if err != nil { + return nil, err + } + contract, err := bindOperatorFactory(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &OperatorFactory{address: address, abi: abi, OperatorFactoryCaller: OperatorFactoryCaller{contract: contract}, OperatorFactoryTransactor: OperatorFactoryTransactor{contract: contract}, OperatorFactoryFilterer: OperatorFactoryFilterer{contract: contract}}, nil +} + +func NewOperatorFactoryCaller(address common.Address, caller bind.ContractCaller) (*OperatorFactoryCaller, error) { + contract, err := bindOperatorFactory(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &OperatorFactoryCaller{contract: contract}, nil +} + +func NewOperatorFactoryTransactor(address common.Address, transactor bind.ContractTransactor) (*OperatorFactoryTransactor, error) { + contract, err := bindOperatorFactory(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &OperatorFactoryTransactor{contract: contract}, nil +} + +func NewOperatorFactoryFilterer(address common.Address, filterer bind.ContractFilterer) (*OperatorFactoryFilterer, error) { + contract, err := bindOperatorFactory(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &OperatorFactoryFilterer{contract: contract}, nil +} + +func bindOperatorFactory(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := OperatorFactoryMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_OperatorFactory *OperatorFactoryRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _OperatorFactory.Contract.OperatorFactoryCaller.contract.Call(opts, result, method, params...) +} + +func (_OperatorFactory *OperatorFactoryRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OperatorFactory.Contract.OperatorFactoryTransactor.contract.Transfer(opts) +} + +func (_OperatorFactory *OperatorFactoryRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _OperatorFactory.Contract.OperatorFactoryTransactor.contract.Transact(opts, method, params...) +} + +func (_OperatorFactory *OperatorFactoryCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _OperatorFactory.Contract.contract.Call(opts, result, method, params...) +} + +func (_OperatorFactory *OperatorFactoryTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OperatorFactory.Contract.contract.Transfer(opts) +} + +func (_OperatorFactory *OperatorFactoryTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _OperatorFactory.Contract.contract.Transact(opts, method, params...) +} + +func (_OperatorFactory *OperatorFactoryCaller) Created(opts *bind.CallOpts, query common.Address) (bool, error) { + var out []interface{} + err := _OperatorFactory.contract.Call(opts, &out, "created", query) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_OperatorFactory *OperatorFactorySession) Created(query common.Address) (bool, error) { + return _OperatorFactory.Contract.Created(&_OperatorFactory.CallOpts, query) +} + +func (_OperatorFactory *OperatorFactoryCallerSession) Created(query common.Address) (bool, error) { + return _OperatorFactory.Contract.Created(&_OperatorFactory.CallOpts, query) +} + +func (_OperatorFactory *OperatorFactoryCaller) LinkToken(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _OperatorFactory.contract.Call(opts, &out, "linkToken") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_OperatorFactory *OperatorFactorySession) LinkToken() (common.Address, error) { + return _OperatorFactory.Contract.LinkToken(&_OperatorFactory.CallOpts) +} + +func (_OperatorFactory *OperatorFactoryCallerSession) LinkToken() (common.Address, error) { + return _OperatorFactory.Contract.LinkToken(&_OperatorFactory.CallOpts) +} + +func (_OperatorFactory *OperatorFactoryCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _OperatorFactory.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_OperatorFactory *OperatorFactorySession) TypeAndVersion() (string, error) { + return _OperatorFactory.Contract.TypeAndVersion(&_OperatorFactory.CallOpts) +} + +func (_OperatorFactory *OperatorFactoryCallerSession) TypeAndVersion() (string, error) { + return _OperatorFactory.Contract.TypeAndVersion(&_OperatorFactory.CallOpts) +} + +func (_OperatorFactory *OperatorFactoryTransactor) DeployNewForwarder(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OperatorFactory.contract.Transact(opts, "deployNewForwarder") +} + +func (_OperatorFactory *OperatorFactorySession) DeployNewForwarder() (*types.Transaction, error) { + return _OperatorFactory.Contract.DeployNewForwarder(&_OperatorFactory.TransactOpts) +} + +func (_OperatorFactory *OperatorFactoryTransactorSession) DeployNewForwarder() (*types.Transaction, error) { + return _OperatorFactory.Contract.DeployNewForwarder(&_OperatorFactory.TransactOpts) +} + +func (_OperatorFactory *OperatorFactoryTransactor) DeployNewForwarderAndTransferOwnership(opts *bind.TransactOpts, to common.Address, message []byte) (*types.Transaction, error) { + return _OperatorFactory.contract.Transact(opts, "deployNewForwarderAndTransferOwnership", to, message) +} + +func (_OperatorFactory *OperatorFactorySession) DeployNewForwarderAndTransferOwnership(to common.Address, message []byte) (*types.Transaction, error) { + return _OperatorFactory.Contract.DeployNewForwarderAndTransferOwnership(&_OperatorFactory.TransactOpts, to, message) +} + +func (_OperatorFactory *OperatorFactoryTransactorSession) DeployNewForwarderAndTransferOwnership(to common.Address, message []byte) (*types.Transaction, error) { + return _OperatorFactory.Contract.DeployNewForwarderAndTransferOwnership(&_OperatorFactory.TransactOpts, to, message) +} + +func (_OperatorFactory *OperatorFactoryTransactor) DeployNewOperator(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OperatorFactory.contract.Transact(opts, "deployNewOperator") +} + +func (_OperatorFactory *OperatorFactorySession) DeployNewOperator() (*types.Transaction, error) { + return _OperatorFactory.Contract.DeployNewOperator(&_OperatorFactory.TransactOpts) +} + +func (_OperatorFactory *OperatorFactoryTransactorSession) DeployNewOperator() (*types.Transaction, error) { + return _OperatorFactory.Contract.DeployNewOperator(&_OperatorFactory.TransactOpts) +} + +func (_OperatorFactory *OperatorFactoryTransactor) DeployNewOperatorAndForwarder(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OperatorFactory.contract.Transact(opts, "deployNewOperatorAndForwarder") +} + +func (_OperatorFactory *OperatorFactorySession) DeployNewOperatorAndForwarder() (*types.Transaction, error) { + return _OperatorFactory.Contract.DeployNewOperatorAndForwarder(&_OperatorFactory.TransactOpts) +} + +func (_OperatorFactory *OperatorFactoryTransactorSession) DeployNewOperatorAndForwarder() (*types.Transaction, error) { + return _OperatorFactory.Contract.DeployNewOperatorAndForwarder(&_OperatorFactory.TransactOpts) +} + +type OperatorFactoryAuthorizedForwarderCreatedIterator struct { + Event *OperatorFactoryAuthorizedForwarderCreated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OperatorFactoryAuthorizedForwarderCreatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OperatorFactoryAuthorizedForwarderCreated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(OperatorFactoryAuthorizedForwarderCreated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *OperatorFactoryAuthorizedForwarderCreatedIterator) Error() error { + return it.fail +} + +func (it *OperatorFactoryAuthorizedForwarderCreatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OperatorFactoryAuthorizedForwarderCreated struct { + Forwarder common.Address + Owner common.Address + Sender common.Address + Raw types.Log +} + +func (_OperatorFactory *OperatorFactoryFilterer) FilterAuthorizedForwarderCreated(opts *bind.FilterOpts, forwarder []common.Address, owner []common.Address, sender []common.Address) (*OperatorFactoryAuthorizedForwarderCreatedIterator, error) { + + var forwarderRule []interface{} + for _, forwarderItem := range forwarder { + forwarderRule = append(forwarderRule, forwarderItem) + } + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _OperatorFactory.contract.FilterLogs(opts, "AuthorizedForwarderCreated", forwarderRule, ownerRule, senderRule) + if err != nil { + return nil, err + } + return &OperatorFactoryAuthorizedForwarderCreatedIterator{contract: _OperatorFactory.contract, event: "AuthorizedForwarderCreated", logs: logs, sub: sub}, nil +} + +func (_OperatorFactory *OperatorFactoryFilterer) WatchAuthorizedForwarderCreated(opts *bind.WatchOpts, sink chan<- *OperatorFactoryAuthorizedForwarderCreated, forwarder []common.Address, owner []common.Address, sender []common.Address) (event.Subscription, error) { + + var forwarderRule []interface{} + for _, forwarderItem := range forwarder { + forwarderRule = append(forwarderRule, forwarderItem) + } + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _OperatorFactory.contract.WatchLogs(opts, "AuthorizedForwarderCreated", forwarderRule, ownerRule, senderRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OperatorFactoryAuthorizedForwarderCreated) + if err := _OperatorFactory.contract.UnpackLog(event, "AuthorizedForwarderCreated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_OperatorFactory *OperatorFactoryFilterer) ParseAuthorizedForwarderCreated(log types.Log) (*OperatorFactoryAuthorizedForwarderCreated, error) { + event := new(OperatorFactoryAuthorizedForwarderCreated) + if err := _OperatorFactory.contract.UnpackLog(event, "AuthorizedForwarderCreated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OperatorFactoryOperatorCreatedIterator struct { + Event *OperatorFactoryOperatorCreated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OperatorFactoryOperatorCreatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OperatorFactoryOperatorCreated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(OperatorFactoryOperatorCreated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *OperatorFactoryOperatorCreatedIterator) Error() error { + return it.fail +} + +func (it *OperatorFactoryOperatorCreatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OperatorFactoryOperatorCreated struct { + Operator common.Address + Owner common.Address + Sender common.Address + Raw types.Log +} + +func (_OperatorFactory *OperatorFactoryFilterer) FilterOperatorCreated(opts *bind.FilterOpts, operator []common.Address, owner []common.Address, sender []common.Address) (*OperatorFactoryOperatorCreatedIterator, error) { + + var operatorRule []interface{} + for _, operatorItem := range operator { + operatorRule = append(operatorRule, operatorItem) + } + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _OperatorFactory.contract.FilterLogs(opts, "OperatorCreated", operatorRule, ownerRule, senderRule) + if err != nil { + return nil, err + } + return &OperatorFactoryOperatorCreatedIterator{contract: _OperatorFactory.contract, event: "OperatorCreated", logs: logs, sub: sub}, nil +} + +func (_OperatorFactory *OperatorFactoryFilterer) WatchOperatorCreated(opts *bind.WatchOpts, sink chan<- *OperatorFactoryOperatorCreated, operator []common.Address, owner []common.Address, sender []common.Address) (event.Subscription, error) { + + var operatorRule []interface{} + for _, operatorItem := range operator { + operatorRule = append(operatorRule, operatorItem) + } + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _OperatorFactory.contract.WatchLogs(opts, "OperatorCreated", operatorRule, ownerRule, senderRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OperatorFactoryOperatorCreated) + if err := _OperatorFactory.contract.UnpackLog(event, "OperatorCreated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_OperatorFactory *OperatorFactoryFilterer) ParseOperatorCreated(log types.Log) (*OperatorFactoryOperatorCreated, error) { + event := new(OperatorFactoryOperatorCreated) + if err := _OperatorFactory.contract.UnpackLog(event, "OperatorCreated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_OperatorFactory *OperatorFactory) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _OperatorFactory.abi.Events["AuthorizedForwarderCreated"].ID: + return _OperatorFactory.ParseAuthorizedForwarderCreated(log) + case _OperatorFactory.abi.Events["OperatorCreated"].ID: + return _OperatorFactory.ParseOperatorCreated(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (OperatorFactoryAuthorizedForwarderCreated) Topic() common.Hash { + return common.HexToHash("0x1c9576ab03e40fdf23673f82d904a0f029c8a6629272a4edad4be877e83af64b") +} + +func (OperatorFactoryOperatorCreated) Topic() common.Hash { + return common.HexToHash("0xd3bb727b2e716a1f142bc9c63c66fe0ae4c5fbc89234f8aa77d0c864a7b63bab") +} + +func (_OperatorFactory *OperatorFactory) Address() common.Address { + return _OperatorFactory.address +} + +type OperatorFactoryInterface interface { + Created(opts *bind.CallOpts, query common.Address) (bool, error) + + LinkToken(opts *bind.CallOpts) (common.Address, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + DeployNewForwarder(opts *bind.TransactOpts) (*types.Transaction, error) + + DeployNewForwarderAndTransferOwnership(opts *bind.TransactOpts, to common.Address, message []byte) (*types.Transaction, error) + + DeployNewOperator(opts *bind.TransactOpts) (*types.Transaction, error) + + DeployNewOperatorAndForwarder(opts *bind.TransactOpts) (*types.Transaction, error) + + FilterAuthorizedForwarderCreated(opts *bind.FilterOpts, forwarder []common.Address, owner []common.Address, sender []common.Address) (*OperatorFactoryAuthorizedForwarderCreatedIterator, error) + + WatchAuthorizedForwarderCreated(opts *bind.WatchOpts, sink chan<- *OperatorFactoryAuthorizedForwarderCreated, forwarder []common.Address, owner []common.Address, sender []common.Address) (event.Subscription, error) + + ParseAuthorizedForwarderCreated(log types.Log) (*OperatorFactoryAuthorizedForwarderCreated, error) + + FilterOperatorCreated(opts *bind.FilterOpts, operator []common.Address, owner []common.Address, sender []common.Address) (*OperatorFactoryOperatorCreatedIterator, error) + + WatchOperatorCreated(opts *bind.WatchOpts, sink chan<- *OperatorFactoryOperatorCreated, operator []common.Address, owner []common.Address, sender []common.Address) (event.Subscription, error) + + ParseOperatorCreated(log types.Log) (*OperatorFactoryOperatorCreated, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/operatorforwarder/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/operatorforwarder/generation/generated-wrapper-dependency-versions-do-not-edit.txt new file mode 100644 index 00000000000..1569801b3fb --- /dev/null +++ b/core/gethwrappers/operatorforwarder/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -0,0 +1,6 @@ +GETH_VERSION: 1.13.8 +authorized_forwarder: ../../../contracts/solc/v0.8.19/AuthorizedForwarder/AuthorizedForwarder.abi ../../../contracts/solc/v0.8.19/AuthorizedForwarder/AuthorizedForwarder.bin 8ea76c883d460f8353a45a493f2aebeb5a2d9a7b4619d1bc4fff5fb590bb3e10 +authorized_receiver: ../../../contracts/solc/v0.8.19/AuthorizedReceiver/AuthorizedReceiver.abi ../../../contracts/solc/v0.8.19/AuthorizedReceiver/AuthorizedReceiver.bin 18e8969ba3234b027e1b16c11a783aca58d0ea5c2361010ec597f134b7bf1c4f +link_token_receiver: ../../../contracts/solc/v0.8.19/LinkTokenReceiver/LinkTokenReceiver.abi ../../../contracts/solc/v0.8.19/LinkTokenReceiver/LinkTokenReceiver.bin 839552e2bea179bdf2591805422fb33769c1646d5a014a00fc2c0cd9c03ef229 +operator: ../../../contracts/solc/v0.8.19/Operator/Operator.abi ../../../contracts/solc/v0.8.19/Operator/Operator.bin 23c3888eaa7259e6adf2153d09abae8f4b1987dc44200363faab1e65483f32d5 +operator_factory: ../../../contracts/solc/v0.8.19/OperatorFactory/OperatorFactory.abi ../../../contracts/solc/v0.8.19/OperatorFactory/OperatorFactory.bin 88e6baa5d9b255eea02616fbcb2cbe21a25ab46adeb6395f6289d169dec949ae diff --git a/core/gethwrappers/operatorforwarder/go_generate.go b/core/gethwrappers/operatorforwarder/go_generate.go new file mode 100644 index 00000000000..074eccdaf4d --- /dev/null +++ b/core/gethwrappers/operatorforwarder/go_generate.go @@ -0,0 +1,10 @@ +// Package gethwrappers provides tools for wrapping solidity contracts with +// golang packages, using abigen. +package gethwrappers + +// Chainlink Operator Forwarder contracts +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/AuthorizedForwarder/AuthorizedForwarder.abi ../../../contracts/solc/v0.8.19/AuthorizedForwarder/AuthorizedForwarder.bin AuthorizedForwarder authorized_forwarder +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/AuthorizedReceiver/AuthorizedReceiver.abi ../../../contracts/solc/v0.8.19/AuthorizedReceiver/AuthorizedReceiver.bin AuthorizedReceiver authorized_receiver +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/LinkTokenReceiver/LinkTokenReceiver.abi ../../../contracts/solc/v0.8.19/LinkTokenReceiver/LinkTokenReceiver.bin LinkTokenReceiver link_token_receiver +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/Operator/Operator.abi ../../../contracts/solc/v0.8.19/Operator/Operator.bin Operator operator +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/OperatorFactory/OperatorFactory.abi ../../../contracts/solc/v0.8.19/OperatorFactory/OperatorFactory.bin OperatorFactory operator_factory From 29b16360fb41e4372f72fe744aaf3ee8234a9b67 Mon Sep 17 00:00:00 2001 From: Lei Date: Fri, 3 May 2024 10:49:28 -0700 Subject: [PATCH 39/45] get available erc20 for finance payment (#13088) --- .changeset/tall-hats-brake.md | 5 ++++ contracts/.changeset/proud-tables-grab.md | 5 ++++ .../v2_3/IAutomationRegistryMaster2_3.sol | 5 ++-- .../dev/test/AutomationRegistry2_3.t.sol | 19 ++++++++++++++ .../dev/v2_3/AutomationRegistryLogicC2_3.sol | 7 +++++ ..._automation_registry_master_wrapper_2_3.go | 26 ++++++++++++++++++- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 7 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 .changeset/tall-hats-brake.md create mode 100644 contracts/.changeset/proud-tables-grab.md diff --git a/.changeset/tall-hats-brake.md b/.changeset/tall-hats-brake.md new file mode 100644 index 00000000000..1c11e4baeca --- /dev/null +++ b/.changeset/tall-hats-brake.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +get available erc20 for payment #bugfix diff --git a/contracts/.changeset/proud-tables-grab.md b/contracts/.changeset/proud-tables-grab.md new file mode 100644 index 00000000000..f2799f86ee9 --- /dev/null +++ b/contracts/.changeset/proud-tables-grab.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +get available erc20s for payment #bugfix diff --git a/contracts/src/v0.8/automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol b/contracts/src/v0.8/automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol index c0952963366..01b19cb480f 100644 --- a/contracts/src/v0.8/automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol +++ b/contracts/src/v0.8/automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol @@ -1,4 +1,4 @@ -// abi-checksum: 0x2cc33080c864676d572ad7ae658ea4a4621b3fd4c4664d84f9945b2324348434 +// abi-checksum: 0xa0e676f1c24f6a43a512fe7141593fb4d4cd6b16c5dcdb0bca2c32e9b135f58a // SPDX-License-Identifier: MIT // !! THIS FILE WAS AUTOGENERATED BY abi-to-sol v0.6.6. SEE SOURCE BELOW. !! pragma solidity ^0.8.4; @@ -228,6 +228,7 @@ interface IAutomationRegistryMaster2_3 { function getAdminPrivilegeConfig(address admin) external view returns (bytes memory); function getAllowedReadOnlyAddress() external view returns (address); function getAutomationForwarderLogic() external view returns (address); + function getAvailableERC20ForPayment(address billingToken) external view returns (uint256); function getBalance(uint256 id) external view returns (uint96 balance); function getBillingConfig( address billingToken @@ -417,5 +418,5 @@ interface IAutomationV21PlusCommon { // THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON: /* -[{"inputs":[{"internalType":"contract AutomationRegistryLogicA2_3","name":"logicA","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayHasNoEntries","type":"error"},{"inputs":[],"name":"CannotCancel","type":"error"},{"inputs":[],"name":"CheckDataExceedsLimit","type":"error"},{"inputs":[],"name":"ConfigDigestMismatch","type":"error"},{"inputs":[],"name":"DuplicateEntry","type":"error"},{"inputs":[],"name":"DuplicateSigners","type":"error"},{"inputs":[],"name":"GasLimitCanOnlyIncrease","type":"error"},{"inputs":[],"name":"GasLimitOutsideRange","type":"error"},{"inputs":[],"name":"IncorrectNumberOfFaultyOracles","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSignatures","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSigners","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"available","type":"uint256"},{"internalType":"uint256","name":"requested","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InsufficientLinkLiquidity","type":"error"},{"inputs":[],"name":"InvalidDataLength","type":"error"},{"inputs":[],"name":"InvalidFeed","type":"error"},{"inputs":[],"name":"InvalidPayee","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidReport","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"InvalidTransmitter","type":"error"},{"inputs":[],"name":"InvalidTrigger","type":"error"},{"inputs":[],"name":"InvalidTriggerType","type":"error"},{"inputs":[],"name":"MigrationNotPermitted","type":"error"},{"inputs":[],"name":"MustSettleOffchain","type":"error"},{"inputs":[],"name":"MustSettleOnchain","type":"error"},{"inputs":[],"name":"NotAContract","type":"error"},{"inputs":[],"name":"OnlyActiveSigners","type":"error"},{"inputs":[],"name":"OnlyActiveTransmitters","type":"error"},{"inputs":[],"name":"OnlyCallableByAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByLINKToken","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrRegistrar","type":"error"},{"inputs":[],"name":"OnlyCallableByPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByUpkeepPrivilegeManager","type":"error"},{"inputs":[],"name":"OnlyFinanceAdmin","type":"error"},{"inputs":[],"name":"OnlyPausedUpkeep","type":"error"},{"inputs":[],"name":"OnlySimulatedBackend","type":"error"},{"inputs":[],"name":"OnlyUnpausedUpkeep","type":"error"},{"inputs":[],"name":"ParameterLengthError","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"inputs":[],"name":"RegistryPaused","type":"error"},{"inputs":[],"name":"RepeatedSigner","type":"error"},{"inputs":[],"name":"RepeatedTransmitter","type":"error"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"TargetCheckReverted","type":"error"},{"inputs":[],"name":"TooManyOracles","type":"error"},{"inputs":[],"name":"TranscoderNotSet","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"UpkeepAlreadyExists","type":"error"},{"inputs":[],"name":"UpkeepCancelled","type":"error"},{"inputs":[],"name":"UpkeepNotCanceled","type":"error"},{"inputs":[],"name":"UpkeepNotNeeded","type":"error"},{"inputs":[],"name":"ValueNotChanged","type":"error"},{"inputs":[],"name":"ZeroAddressNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"AdminPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"overrides","type":"tuple"}],"name":"BillingConfigOverridden","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"BillingConfigOverrideRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20Metadata","name":"token","type":"address"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"config","type":"tuple"}],"name":"BillingConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"CancelledUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newModule","type":"address"}],"name":"ChainSpecificModuleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"previousConfigBlockNumber","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"configCount","type":"uint64"},{"indexed":false,"internalType":"address[]","name":"signers","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"uint8","name":"f","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"onchainConfig","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"DedupKeyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"assetAddress","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"}],"name":"FundsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"InsufficientFundsUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"payments","type":"uint256[]"}],"name":"NOPsSettledOffchain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"}],"name":"PayeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"payee","type":"address"}],"name":"PaymentWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"ReorgedUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"StaleUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"}],"name":"Transmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint64","name":"atBlockHeight","type":"uint64"}],"name":"UpkeepCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"UpkeepCheckDataSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint96","name":"gasLimit","type":"uint96"}],"name":"UpkeepGasLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"UpkeepMigrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"UpkeepOffchainConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint96","name":"totalPayment","type":"uint96"},{"indexed":false,"internalType":"uint256","name":"gasUsed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasOverhead","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"UpkeepPerformed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"UpkeepPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"importedFrom","type":"address"}],"name":"UpkeepReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"performGas","type":"uint32"},{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"UpkeepRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"UpkeepTriggerConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepUnpaused","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fallbackTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDetails","outputs":[{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDigestAndEpoch","outputs":[{"internalType":"bool","name":"scanLogs","type":"bool"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"internalType":"uint32","name":"epoch","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onTokenTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bytes","name":"onchainConfigBytes","type":"bytes"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"onchainConfig","type":"tuple"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"},{"internalType":"contract IERC20Metadata[]","name":"billingTokens","type":"address[]"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig[]","name":"billingConfigs","type":"tuple[]"}],"name":"setConfigTypeSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[3]","name":"reportContext","type":"bytes32[3]"},{"internalType":"bytes","name":"rawReport","type":"bytes"},{"internalType":"bytes32[]","name":"rs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ss","type":"bytes32[]"},{"internalType":"bytes32","name":"rawVs","type":"bytes32"}],"name":"transmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicB2_3","name":"logicB","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"cancelUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"address","name":"destination","type":"address"}],"name":"migrateUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedUpkeeps","type":"bytes"}],"name":"receiveUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"registerUpkeep","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicC2_3","name":"logicC","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"acceptUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"addFunds","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes[]","name":"values","type":"bytes[]"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"checkCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerData","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"executeCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"pauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"removeBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"billingOverrides","type":"tuple"}],"name":"setBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"setUpkeepCheckData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"name":"setUpkeepGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"config","type":"bytes"}],"name":"setUpkeepOffchainConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"setUpkeepTriggerConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"simulatePerformUpkeep","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"unpauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"asset","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawERC20Fees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawLink","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"link","type":"address"},{"internalType":"address","name":"linkUSDFeed","type":"address"},{"internalType":"address","name":"nativeUSDFeed","type":"address"},{"internalType":"address","name":"fastGasFeed","type":"address"},{"internalType":"address","name":"automationForwarderLogic","type":"address"},{"internalType":"address","name":"allowedReadOnlyAddress","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"payoutMode","type":"uint8"},{"internalType":"address","name":"wrappedNativeTokenAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"}],"name":"acceptPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableOffchainPayments","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"maxCount","type":"uint256"}],"name":"getActiveUpkeepIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"getAdminPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllowedReadOnlyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAutomationForwarderLogic","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getBalance","outputs":[{"internalType":"uint96","name":"balance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getBillingConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingOverrides","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingToken","outputs":[{"internalType":"contract IERC20Metadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"getBillingTokenConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBillingTokens","outputs":[{"internalType":"contract IERC20Metadata[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCancellationDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getChainModule","outputs":[{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConditionalGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getConfig","outputs":[{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFallbackNativePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFastGasFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getForwarder","outputs":[{"internalType":"contract IAutomationForwarder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getHotVars","outputs":[{"components":[{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"reentrancyGuard","type":"bool"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.HotVars","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLogGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getMaxPaymentForGas","outputs":[{"internalType":"uint96","name":"maxPayment","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalance","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalanceForUpkeep","outputs":[{"internalType":"uint96","name":"minBalance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNativeUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumUpkeeps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPayoutMode","outputs":[{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"}],"name":"getPeerRegistryMigrationPermission","outputs":[{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPerPerformByteGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getPerSignerGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getReorgProtectionEnabled","outputs":[{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getReserveAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getSignerInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"components":[{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint96","name":"ownerLinkBalance","type":"uint96"},{"internalType":"uint256","name":"expectedLinkBalance","type":"uint256"},{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint256","name":"numUpkeeps","type":"uint256"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"bytes32","name":"latestConfigDigest","type":"bytes32"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"bool","name":"paused","type":"bool"}],"internalType":"struct IAutomationV21PlusCommon.StateLegacy","name":"state","type":"tuple"},{"components":[{"internalType":"uint32","name":"paymentPremiumPPB","type":"uint32"},{"internalType":"uint32","name":"flatFeeMicroLink","type":"uint32"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint96","name":"minUpkeepSpend","type":"uint96"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"}],"internalType":"struct IAutomationV21PlusCommon.OnchainConfigLegacy","name":"config","type":"tuple"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStorage","outputs":[{"components":[{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"}],"internalType":"struct AutomationRegistryBase2_3.Storage","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmitCalldataFixedBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getTransmitCalldataPerSignerBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getTransmitterInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint96","name":"lastCollected","type":"uint96"},{"internalType":"address","name":"payee","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmittersWithPayees","outputs":[{"components":[{"internalType":"address","name":"transmitterAddress","type":"address"},{"internalType":"address","name":"payeeAddress","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.TransmitterPayeeInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getTriggerType","outputs":[{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getUpkeep","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"performGas","type":"uint32"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint64","name":"maxValidBlocknumber","type":"uint64"},{"internalType":"uint32","name":"lastPerformedBlockNumber","type":"uint32"},{"internalType":"uint96","name":"amountSpent","type":"uint96"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"internalType":"struct IAutomationV21PlusCommon.UpkeepInfoLegacy","name":"upkeepInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepTriggerConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWrappedNativeTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"hasDedupKey","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"linkAvailableForPayment","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setAdminPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"payees","type":"address[]"}],"name":"setPayees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"permission","type":"uint8"}],"name":"setPeerRegistryMigrationPermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setUpkeepPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleNOPsOffchain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"supportsBillingToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upkeepVersion","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawPayment","outputs":[],"stateMutability":"nonpayable","type":"function"}] +[{"inputs":[{"internalType":"contract AutomationRegistryLogicA2_3","name":"logicA","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayHasNoEntries","type":"error"},{"inputs":[],"name":"CannotCancel","type":"error"},{"inputs":[],"name":"CheckDataExceedsLimit","type":"error"},{"inputs":[],"name":"ConfigDigestMismatch","type":"error"},{"inputs":[],"name":"DuplicateEntry","type":"error"},{"inputs":[],"name":"DuplicateSigners","type":"error"},{"inputs":[],"name":"GasLimitCanOnlyIncrease","type":"error"},{"inputs":[],"name":"GasLimitOutsideRange","type":"error"},{"inputs":[],"name":"IncorrectNumberOfFaultyOracles","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSignatures","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSigners","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"available","type":"uint256"},{"internalType":"uint256","name":"requested","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InsufficientLinkLiquidity","type":"error"},{"inputs":[],"name":"InvalidDataLength","type":"error"},{"inputs":[],"name":"InvalidFeed","type":"error"},{"inputs":[],"name":"InvalidPayee","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidReport","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"InvalidTransmitter","type":"error"},{"inputs":[],"name":"InvalidTrigger","type":"error"},{"inputs":[],"name":"InvalidTriggerType","type":"error"},{"inputs":[],"name":"MigrationNotPermitted","type":"error"},{"inputs":[],"name":"MustSettleOffchain","type":"error"},{"inputs":[],"name":"MustSettleOnchain","type":"error"},{"inputs":[],"name":"NotAContract","type":"error"},{"inputs":[],"name":"OnlyActiveSigners","type":"error"},{"inputs":[],"name":"OnlyActiveTransmitters","type":"error"},{"inputs":[],"name":"OnlyCallableByAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByLINKToken","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrRegistrar","type":"error"},{"inputs":[],"name":"OnlyCallableByPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByUpkeepPrivilegeManager","type":"error"},{"inputs":[],"name":"OnlyFinanceAdmin","type":"error"},{"inputs":[],"name":"OnlyPausedUpkeep","type":"error"},{"inputs":[],"name":"OnlySimulatedBackend","type":"error"},{"inputs":[],"name":"OnlyUnpausedUpkeep","type":"error"},{"inputs":[],"name":"ParameterLengthError","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"inputs":[],"name":"RegistryPaused","type":"error"},{"inputs":[],"name":"RepeatedSigner","type":"error"},{"inputs":[],"name":"RepeatedTransmitter","type":"error"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"TargetCheckReverted","type":"error"},{"inputs":[],"name":"TooManyOracles","type":"error"},{"inputs":[],"name":"TranscoderNotSet","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"UpkeepAlreadyExists","type":"error"},{"inputs":[],"name":"UpkeepCancelled","type":"error"},{"inputs":[],"name":"UpkeepNotCanceled","type":"error"},{"inputs":[],"name":"UpkeepNotNeeded","type":"error"},{"inputs":[],"name":"ValueNotChanged","type":"error"},{"inputs":[],"name":"ZeroAddressNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"AdminPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"overrides","type":"tuple"}],"name":"BillingConfigOverridden","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"BillingConfigOverrideRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20Metadata","name":"token","type":"address"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"config","type":"tuple"}],"name":"BillingConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"CancelledUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newModule","type":"address"}],"name":"ChainSpecificModuleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"previousConfigBlockNumber","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"configCount","type":"uint64"},{"indexed":false,"internalType":"address[]","name":"signers","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"uint8","name":"f","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"onchainConfig","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"DedupKeyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"assetAddress","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"}],"name":"FundsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"InsufficientFundsUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"payments","type":"uint256[]"}],"name":"NOPsSettledOffchain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"}],"name":"PayeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"payee","type":"address"}],"name":"PaymentWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"ReorgedUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"StaleUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"}],"name":"Transmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint64","name":"atBlockHeight","type":"uint64"}],"name":"UpkeepCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"UpkeepCheckDataSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint96","name":"gasLimit","type":"uint96"}],"name":"UpkeepGasLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"UpkeepMigrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"UpkeepOffchainConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint96","name":"totalPayment","type":"uint96"},{"indexed":false,"internalType":"uint256","name":"gasUsed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasOverhead","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"UpkeepPerformed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"UpkeepPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"importedFrom","type":"address"}],"name":"UpkeepReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"performGas","type":"uint32"},{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"UpkeepRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"UpkeepTriggerConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepUnpaused","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fallbackTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDetails","outputs":[{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDigestAndEpoch","outputs":[{"internalType":"bool","name":"scanLogs","type":"bool"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"internalType":"uint32","name":"epoch","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onTokenTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bytes","name":"onchainConfigBytes","type":"bytes"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"onchainConfig","type":"tuple"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"},{"internalType":"contract IERC20Metadata[]","name":"billingTokens","type":"address[]"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig[]","name":"billingConfigs","type":"tuple[]"}],"name":"setConfigTypeSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[3]","name":"reportContext","type":"bytes32[3]"},{"internalType":"bytes","name":"rawReport","type":"bytes"},{"internalType":"bytes32[]","name":"rs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ss","type":"bytes32[]"},{"internalType":"bytes32","name":"rawVs","type":"bytes32"}],"name":"transmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicB2_3","name":"logicB","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"cancelUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"address","name":"destination","type":"address"}],"name":"migrateUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedUpkeeps","type":"bytes"}],"name":"receiveUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"registerUpkeep","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicC2_3","name":"logicC","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"acceptUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"addFunds","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes[]","name":"values","type":"bytes[]"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"checkCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerData","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"executeCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"pauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"removeBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"billingOverrides","type":"tuple"}],"name":"setBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"setUpkeepCheckData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"name":"setUpkeepGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"config","type":"bytes"}],"name":"setUpkeepOffchainConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"setUpkeepTriggerConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"simulatePerformUpkeep","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"unpauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"asset","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawERC20Fees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawLink","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"link","type":"address"},{"internalType":"address","name":"linkUSDFeed","type":"address"},{"internalType":"address","name":"nativeUSDFeed","type":"address"},{"internalType":"address","name":"fastGasFeed","type":"address"},{"internalType":"address","name":"automationForwarderLogic","type":"address"},{"internalType":"address","name":"allowedReadOnlyAddress","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"payoutMode","type":"uint8"},{"internalType":"address","name":"wrappedNativeTokenAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"}],"name":"acceptPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableOffchainPayments","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"maxCount","type":"uint256"}],"name":"getActiveUpkeepIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"getAdminPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllowedReadOnlyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAutomationForwarderLogic","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getAvailableERC20ForPayment","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getBalance","outputs":[{"internalType":"uint96","name":"balance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getBillingConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingOverrides","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingToken","outputs":[{"internalType":"contract IERC20Metadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"getBillingTokenConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBillingTokens","outputs":[{"internalType":"contract IERC20Metadata[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCancellationDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getChainModule","outputs":[{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConditionalGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getConfig","outputs":[{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFallbackNativePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFastGasFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getForwarder","outputs":[{"internalType":"contract IAutomationForwarder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getHotVars","outputs":[{"components":[{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"reentrancyGuard","type":"bool"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.HotVars","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLogGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getMaxPaymentForGas","outputs":[{"internalType":"uint96","name":"maxPayment","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalance","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalanceForUpkeep","outputs":[{"internalType":"uint96","name":"minBalance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNativeUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumUpkeeps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPayoutMode","outputs":[{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"}],"name":"getPeerRegistryMigrationPermission","outputs":[{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPerPerformByteGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getPerSignerGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getReorgProtectionEnabled","outputs":[{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getReserveAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getSignerInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"components":[{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint96","name":"ownerLinkBalance","type":"uint96"},{"internalType":"uint256","name":"expectedLinkBalance","type":"uint256"},{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint256","name":"numUpkeeps","type":"uint256"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"bytes32","name":"latestConfigDigest","type":"bytes32"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"bool","name":"paused","type":"bool"}],"internalType":"struct IAutomationV21PlusCommon.StateLegacy","name":"state","type":"tuple"},{"components":[{"internalType":"uint32","name":"paymentPremiumPPB","type":"uint32"},{"internalType":"uint32","name":"flatFeeMicroLink","type":"uint32"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint96","name":"minUpkeepSpend","type":"uint96"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"}],"internalType":"struct IAutomationV21PlusCommon.OnchainConfigLegacy","name":"config","type":"tuple"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStorage","outputs":[{"components":[{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"}],"internalType":"struct AutomationRegistryBase2_3.Storage","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmitCalldataFixedBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getTransmitCalldataPerSignerBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getTransmitterInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint96","name":"lastCollected","type":"uint96"},{"internalType":"address","name":"payee","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmittersWithPayees","outputs":[{"components":[{"internalType":"address","name":"transmitterAddress","type":"address"},{"internalType":"address","name":"payeeAddress","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.TransmitterPayeeInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getTriggerType","outputs":[{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getUpkeep","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"performGas","type":"uint32"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint64","name":"maxValidBlocknumber","type":"uint64"},{"internalType":"uint32","name":"lastPerformedBlockNumber","type":"uint32"},{"internalType":"uint96","name":"amountSpent","type":"uint96"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"internalType":"struct IAutomationV21PlusCommon.UpkeepInfoLegacy","name":"upkeepInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepTriggerConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWrappedNativeTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"hasDedupKey","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"linkAvailableForPayment","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setAdminPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"payees","type":"address[]"}],"name":"setPayees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"permission","type":"uint8"}],"name":"setPeerRegistryMigrationPermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setUpkeepPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleNOPsOffchain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"supportsBillingToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upkeepVersion","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawPayment","outputs":[],"stateMutability":"nonpayable","type":"function"}] */ diff --git a/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol b/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol index 6da98e16fe5..ca4075a59c7 100644 --- a/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol +++ b/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol @@ -205,6 +205,7 @@ contract AddFunds is SetUp { registry.addFunds(nativeUpkeepID, 1); assertEq(registry.getBalance(nativeUpkeepID), startRegistryBalance + 1); assertEq(weth.balanceOf(address(registry)), startTokenBalance + 1); + assertEq(registry.getAvailableERC20ForPayment(address(weth)), 0); } // when msg.value is not 0, it uses the native payment path @@ -214,6 +215,7 @@ contract AddFunds is SetUp { registry.addFunds{value: 1}(nativeUpkeepID, 1000); // parameter amount should be ignored assertEq(registry.getBalance(nativeUpkeepID), startRegistryBalance + 1); assertEq(weth.balanceOf(address(registry)), startTokenBalance + 1); + assertEq(registry.getAvailableERC20ForPayment(address(weth)), 0); } // it fails when the billing token is not native, but trying to pay with native @@ -348,6 +350,10 @@ contract Withdraw is SetUp { function test_WithdrawERC20Fees_RevertsWhen_LinkAvailableForPaymentIsNegative() public { _transmit(usdUpkeepID18, registry); // adds USD token to finance withdrawable, and gives NOPs a LINK balance require(registry.linkAvailableForPayment() < 0, "linkAvailableForPayment should be negative"); + require( + registry.getAvailableERC20ForPayment(address(usdToken18)) > 0, + "ERC20AvailableForPayment should be positive" + ); vm.expectRevert(Registry.InsufficientLinkLiquidity.selector); vm.prank(FINANCE_ADMIN); registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, 1); // should revert @@ -1563,8 +1569,21 @@ contract Transmit is SetUp { upkeepIDs[0] = linkUpkeepID; upkeepIDs[1] = usdUpkeepID18; upkeepIDs[2] = nativeUpkeepID; + + // withdraw-able by finance team should be 0 + require(registry.getAvailableERC20ForPayment(address(usdToken18)) == 0, "ERC20AvailableForPayment should be 0"); + require(registry.getAvailableERC20ForPayment(address(weth)) == 0, "ERC20AvailableForPayment should be 0"); + // do the thing _transmit(upkeepIDs, registry); + + // withdraw-able by the finance team should be positive + require( + registry.getAvailableERC20ForPayment(address(usdToken18)) > 0, + "ERC20AvailableForPayment should be positive" + ); + require(registry.getAvailableERC20ForPayment(address(weth)) > 0, "ERC20AvailableForPayment should be positive"); + // assert upkeep balances have decreased require(prevUpkeepBalances[0] > registry.getBalance(linkUpkeepID), "link upkeep balance should have decreased"); require(prevUpkeepBalances[1] > registry.getBalance(usdUpkeepID18), "usd upkeep balance should have decreased"); diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol index d4565615ad1..838e05353c8 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol +++ b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol @@ -584,6 +584,13 @@ contract AutomationRegistryLogicC2_3 is AutomationRegistryBase2_3 { return s_reserveAmounts[billingToken]; } + /** + * @notice returns the amount of a particular token that is withdraw-able by finance admin + */ + function getAvailableERC20ForPayment(IERC20 billingToken) external view returns (uint256) { + return billingToken.balanceOf(address(this)) - s_reserveAmounts[IERC20(address(billingToken))]; + } + /** * @notice returns the size of the LINK liquidity pool */ diff --git a/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3/i_automation_registry_master_wrapper_2_3.go b/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3/i_automation_registry_master_wrapper_2_3.go index cdbb52883ff..2c44939a9a0 100644 --- a/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3/i_automation_registry_master_wrapper_2_3.go +++ b/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3/i_automation_registry_master_wrapper_2_3.go @@ -139,7 +139,7 @@ type IAutomationV21PlusCommonUpkeepInfoLegacy struct { } var IAutomationRegistryMaster23MetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"acceptPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"acceptUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"addFunds\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"cancelUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"checkCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerData\",\"type\":\"bytes\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"disableOffchainPayments\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"executeCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"name\":\"getActiveUpkeepIDs\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"getAdminPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowedReadOnlyAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAutomationForwarderLogic\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getBillingConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingOverrides\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getBillingTokenConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBillingTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCancellationDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainModule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConditionalGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFallbackNativePrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFastGasFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getForwarder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getHotVars\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuard\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.HotVars\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLogGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getMaxPaymentForGas\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"maxPayment\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalanceForUpkeep\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"minBalance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNativeUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumUpkeeps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPayoutMode\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"}],\"name\":\"getPeerRegistryMigrationPermission\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerPerformByteGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerSignerGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReorgProtectionEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getReserveAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getSignerInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"ownerLinkBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"expectedLinkBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"numUpkeeps\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"latestConfigDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"}],\"internalType\":\"structIAutomationV21PlusCommon.StateLegacy\",\"name\":\"state\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"paymentPremiumPPB\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"flatFeeMicroLink\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint96\",\"name\":\"minUpkeepSpend\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"}],\"internalType\":\"structIAutomationV21PlusCommon.OnchainConfigLegacy\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStorage\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistryBase2_3.Storage\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataFixedBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataPerSignerBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getTransmitterInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"lastCollected\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmittersWithPayees\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"transmitterAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payeeAddress\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.TransmitterPayeeInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getTriggerType\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getUpkeep\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"maxValidBlocknumber\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"lastPerformedBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"amountSpent\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structIAutomationV21PlusCommon.UpkeepInfoLegacy\",\"name\":\"upkeepInfo\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepTriggerConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWrappedNativeTokenAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"hasDedupKey\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"linkAvailableForPayment\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"migrateUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"pauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedUpkeeps\",\"type\":\"bytes\"}],\"name\":\"receiveUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"registerUpkeep\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"removeBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setAdminPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"billingOverrides\",\"type\":\"tuple\"}],\"name\":\"setBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfigBytes\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"onchainConfig\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"address[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig[]\",\"name\":\"billingConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConfigTypeSafe\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"setPayees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"permission\",\"type\":\"uint8\"}],\"name\":\"setPeerRegistryMigrationPermission\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"setUpkeepCheckData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"}],\"name\":\"setUpkeepGasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"name\":\"setUpkeepOffchainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"settleNOPsOffchain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"simulatePerformUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"supportsBillingToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"unpauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"upkeepVersion\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawERC20Fees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLink\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawPayment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"acceptPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"acceptUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"addFunds\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"cancelUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"checkCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerData\",\"type\":\"bytes\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"disableOffchainPayments\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"executeCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"name\":\"getActiveUpkeepIDs\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"getAdminPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowedReadOnlyAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAutomationForwarderLogic\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getAvailableERC20ForPayment\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getBillingConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingOverrides\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getBillingTokenConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBillingTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCancellationDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainModule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConditionalGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFallbackNativePrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFastGasFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getForwarder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getHotVars\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuard\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.HotVars\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLogGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getMaxPaymentForGas\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"maxPayment\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalanceForUpkeep\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"minBalance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNativeUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumUpkeeps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPayoutMode\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"}],\"name\":\"getPeerRegistryMigrationPermission\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerPerformByteGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerSignerGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReorgProtectionEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getReserveAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getSignerInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"ownerLinkBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"expectedLinkBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"numUpkeeps\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"latestConfigDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"}],\"internalType\":\"structIAutomationV21PlusCommon.StateLegacy\",\"name\":\"state\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"paymentPremiumPPB\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"flatFeeMicroLink\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint96\",\"name\":\"minUpkeepSpend\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"}],\"internalType\":\"structIAutomationV21PlusCommon.OnchainConfigLegacy\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStorage\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistryBase2_3.Storage\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataFixedBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataPerSignerBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getTransmitterInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"lastCollected\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmittersWithPayees\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"transmitterAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payeeAddress\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.TransmitterPayeeInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getTriggerType\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getUpkeep\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"maxValidBlocknumber\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"lastPerformedBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"amountSpent\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structIAutomationV21PlusCommon.UpkeepInfoLegacy\",\"name\":\"upkeepInfo\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepTriggerConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWrappedNativeTokenAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"hasDedupKey\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"linkAvailableForPayment\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"migrateUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"pauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedUpkeeps\",\"type\":\"bytes\"}],\"name\":\"receiveUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"registerUpkeep\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"removeBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setAdminPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"billingOverrides\",\"type\":\"tuple\"}],\"name\":\"setBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfigBytes\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"onchainConfig\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"address[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig[]\",\"name\":\"billingConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConfigTypeSafe\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"setPayees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"permission\",\"type\":\"uint8\"}],\"name\":\"setPeerRegistryMigrationPermission\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"setUpkeepCheckData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"}],\"name\":\"setUpkeepGasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"name\":\"setUpkeepOffchainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"settleNOPsOffchain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"simulatePerformUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"supportsBillingToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"unpauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"upkeepVersion\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawERC20Fees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLink\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawPayment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", } var IAutomationRegistryMaster23ABI = IAutomationRegistryMaster23MetaData.ABI @@ -472,6 +472,28 @@ func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23CallerSession) Ge return _IAutomationRegistryMaster23.Contract.GetAutomationForwarderLogic(&_IAutomationRegistryMaster23.CallOpts) } +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Caller) GetAvailableERC20ForPayment(opts *bind.CallOpts, billingToken common.Address) (*big.Int, error) { + var out []interface{} + err := _IAutomationRegistryMaster23.contract.Call(opts, &out, "getAvailableERC20ForPayment", billingToken) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Session) GetAvailableERC20ForPayment(billingToken common.Address) (*big.Int, error) { + return _IAutomationRegistryMaster23.Contract.GetAvailableERC20ForPayment(&_IAutomationRegistryMaster23.CallOpts, billingToken) +} + +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23CallerSession) GetAvailableERC20ForPayment(billingToken common.Address) (*big.Int, error) { + return _IAutomationRegistryMaster23.Contract.GetAvailableERC20ForPayment(&_IAutomationRegistryMaster23.CallOpts, billingToken) +} + func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Caller) GetBalance(opts *bind.CallOpts, id *big.Int) (*big.Int, error) { var out []interface{} err := _IAutomationRegistryMaster23.contract.Call(opts, &out, "getBalance", id) @@ -7308,6 +7330,8 @@ type IAutomationRegistryMaster23Interface interface { GetAutomationForwarderLogic(opts *bind.CallOpts) (common.Address, error) + GetAvailableERC20ForPayment(opts *bind.CallOpts, billingToken common.Address) (*big.Int, error) + GetBalance(opts *bind.CallOpts, id *big.Int) (*big.Int, error) GetBillingConfig(opts *bind.CallOpts, billingToken common.Address) (AutomationRegistryBase23BillingConfig, error) diff --git a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt index d5a931321ab..9dbf6e87090 100644 --- a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -31,7 +31,7 @@ dummy_protocol_wrapper: ../../contracts/solc/v0.8.16/DummyProtocol/DummyProtocol gas_wrapper: ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.abi ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.bin 4a5dcdac486d18fcd58e3488c15c1710ae76b977556a3f3191bd269a4bc75723 gas_wrapper_mock: ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.abi ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.bin a9b08f18da59125c6fc305855710241f3d35161b8b9f3e3f635a7b1d5c6da9c8 i_automation_registry_master_wrapper_2_2: ../../contracts/solc/v0.8.19/IAutomationRegistryMaster/IAutomationRegistryMaster.abi ../../contracts/solc/v0.8.19/IAutomationRegistryMaster/IAutomationRegistryMaster.bin 9ff7087179f89f9b05964ebc3e71332fce11f1b8e85058f7b16b3bc0dd6fb96b -i_automation_registry_master_wrapper_2_3: ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.abi ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.bin 19f51996d05341f1229f21be26b5d72ff58e321f0b6da69c260f768e4622ae8e +i_automation_registry_master_wrapper_2_3: ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.abi ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.bin aa65a3c4bc89fadae2f389da6643caad50e9b9948d61e2d40d8f00774f356a80 i_automation_v21_plus_common: ../../contracts/solc/v0.8.19/IAutomationV21PlusCommon/IAutomationV21PlusCommon.abi ../../contracts/solc/v0.8.19/IAutomationV21PlusCommon/IAutomationV21PlusCommon.bin e8a601ec382c0a2e83c49759de13b0622b5e04e6b95901e96a1e9504329e594c i_chain_module: ../../contracts/solc/v0.8.19/IChainModule/IChainModule.abi ../../contracts/solc/v0.8.19/IChainModule/IChainModule.bin 383611981c86c70522f41b8750719faacc7d7933a22849d5004799ebef3371fa i_keeper_registry_master_wrapper_2_1: ../../contracts/solc/v0.8.16/IKeeperRegistryMaster/IKeeperRegistryMaster.abi ../../contracts/solc/v0.8.16/IKeeperRegistryMaster/IKeeperRegistryMaster.bin ee0f150b3afbab2df3d24ff3f4c87851efa635da30db04cd1f70cb4e185a1781 From a34a17ae9d62679a1ff15a7703f5cbcf6dfd1d0f Mon Sep 17 00:00:00 2001 From: Lei Date: Fri, 3 May 2024 11:43:21 -0700 Subject: [PATCH 40/45] finance can withdraw erc20s in offchain mode (#13058) --- .changeset/grumpy-birds-serve.md | 5 ++ contracts/.changeset/calm-maps-vanish.md | 5 ++ .../dev/test/AutomationRegistry2_3.t.sol | 61 ++++++++++++++++++- .../dev/v2_3/AutomationRegistryLogicB2_3.sol | 4 +- ...automation_registry_logic_b_wrapper_2_3.go | 2 +- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 6 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 .changeset/grumpy-birds-serve.md create mode 100644 contracts/.changeset/calm-maps-vanish.md diff --git a/.changeset/grumpy-birds-serve.md b/.changeset/grumpy-birds-serve.md new file mode 100644 index 00000000000..35b2c160c02 --- /dev/null +++ b/.changeset/grumpy-birds-serve.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +withdraw in offchain mode #bugfix diff --git a/contracts/.changeset/calm-maps-vanish.md b/contracts/.changeset/calm-maps-vanish.md new file mode 100644 index 00000000000..e9dfcdd53b0 --- /dev/null +++ b/contracts/.changeset/calm-maps-vanish.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +withdraw in offchain mode #bugfix diff --git a/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol b/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol index ca4075a59c7..5611b11acf0 100644 --- a/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol +++ b/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol @@ -347,6 +347,7 @@ contract Withdraw is SetUp { registry.withdrawLink(FINANCE_ADMIN, 1); // but using link withdraw functions succeeds } + // default is ON_CHAIN mode function test_WithdrawERC20Fees_RevertsWhen_LinkAvailableForPaymentIsNegative() public { _transmit(usdUpkeepID18, registry); // adds USD token to finance withdrawable, and gives NOPs a LINK balance require(registry.linkAvailableForPayment() < 0, "linkAvailableForPayment should be negative"); @@ -362,6 +363,27 @@ contract Withdraw is SetUp { registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, 1); // now finance can withdraw } + function test_WithdrawERC20Fees_InOffChainMode_Happy() public { + // deploy and configure a registry with OFF_CHAIN payout + (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + + // register an upkeep and add funds + uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); + _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); + vm.startPrank(UPKEEP_ADMIN); + usdToken18.approve(address(registry), 1e20); + registry.addFunds(id, 1e20); + + // manually create a transmit so transmitters earn some rewards + _transmit(id, registry); + require(registry.linkAvailableForPayment() < 0, "linkAvailableForPayment should be negative"); + vm.prank(FINANCE_ADMIN); + registry.withdrawERC20Fees(address(usdToken18), aMockAddress, 1); // finance can withdraw + + // recipient should get the funds + assertEq(usdToken18.balanceOf(address(aMockAddress)), 1); + } + function testWithdrawERC20FeeSuccess() public { // deposit excess USDToken to the registry (this goes to the "finance withdrawable" pool be default) uint256 startReserveAmount = registry.getReserveAmount(address(usdToken18)); @@ -965,7 +987,8 @@ contract NOPsSettlement is SetUp { registry.settleNOPsOffchain(); } - function testSettleNOPsOffchainSuccessTransmitterBalanceZeroed() public { + // 1. transmitter balance zeroed after settlement, 2. admin can withdraw ERC20, 3. switch to onchain mode, 4. link amount owed to NOPs stays the same + function testSettleNOPsOffchainSuccessWithERC20MultiSteps() public { // deploy and configure a registry with OFF_CHAIN payout (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); @@ -1007,6 +1030,42 @@ contract NOPsSettlement is SetUp { // after the offchain settlement, the total reserve amount of LINK should be 0 assertEq(registry.getReserveAmount(address(linkToken)), 0); + // should have some ERC20s in registry after transmit + uint256 erc20ForPayment1 = registry.getAvailableERC20ForPayment(address(usdToken18)); + require(erc20ForPayment1 > 0, "ERC20AvailableForPayment should be positive"); + + vm.startPrank(UPKEEP_ADMIN); + vm.roll(100 + block.number); + // manually create a transmit so transmitters earn some rewards + _transmit(id, registry); + + uint256 erc20ForPayment2 = registry.getAvailableERC20ForPayment(address(usdToken18)); + require(erc20ForPayment2 > erc20ForPayment1, "ERC20AvailableForPayment should be greater after another transmit"); + + // finance admin comes to withdraw all available ERC20s + vm.startPrank(FINANCE_ADMIN); + registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, erc20ForPayment2); + + uint256 erc20ForPayment3 = registry.getAvailableERC20ForPayment(address(usdToken18)); + require(erc20ForPayment3 == 0, "ERC20AvailableForPayment should be 0 now after withdrawal"); + + uint256 reservedLink = registry.getReserveAmount(address(linkToken)); + require(reservedLink > 0, "Reserve amount of LINK should be positive since there was another transmit"); + + // owner comes to disable offchain mode + vm.startPrank(registry.owner()); + registry.disableOffchainPayments(); + + // finance admin comes to withdraw all available ERC20s, should revert bc of insufficient link liquidity + vm.startPrank(FINANCE_ADMIN); + uint256 erc20ForPayment4 = registry.getAvailableERC20ForPayment(address(usdToken18)); + vm.expectRevert(abi.encodeWithSelector(Registry.InsufficientLinkLiquidity.selector)); + registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, erc20ForPayment4); + + // reserved link amount to NOPs should stay the same after switching to onchain mode + assertEq(registry.getReserveAmount(address(linkToken)), reservedLink); + // available ERC20 for payment should be 0 since finance admin withdrew all already + assertEq(erc20ForPayment4, 0); } function testSettleNOPsOffchainForDeactivatedTransmittersSuccess() public { diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicB2_3.sol b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicB2_3.sol index d69d5e0bd96..dbdc563d9ba 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicB2_3.sol +++ b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicB2_3.sol @@ -430,14 +430,14 @@ contract AutomationRegistryLogicB2_3 is AutomationRegistryBase2_3, Chainable { * @param asset the asset to withdraw * @param to the address to send the fees to * @param amount the amount to withdraw - * @dev we prevent withdrawing non-LINK fees unless there is sufficient LINK liquidity + * @dev in ON_CHAIN mode, we prevent withdrawing non-LINK fees unless there is sufficient LINK liquidity * to cover all outstanding debts on the registry */ function withdrawERC20Fees(IERC20 asset, address to, uint256 amount) external { _onlyFinanceAdminAllowed(); if (to == ZERO_ADDRESS) revert InvalidRecipient(); if (address(asset) == address(i_link)) revert InvalidToken(); - if (_linkAvailableForPayment() < 0) revert InsufficientLinkLiquidity(); + if (_linkAvailableForPayment() < 0 && s_payoutMode == PayoutMode.ON_CHAIN) revert InsufficientLinkLiquidity(); uint256 available = asset.balanceOf(address(this)) - s_reserveAmounts[asset]; if (amount > available) revert InsufficientBalance(available, amount); diff --git a/core/gethwrappers/generated/automation_registry_logic_b_wrapper_2_3/automation_registry_logic_b_wrapper_2_3.go b/core/gethwrappers/generated/automation_registry_logic_b_wrapper_2_3/automation_registry_logic_b_wrapper_2_3.go index 04087c52e11..7e7c893d4d0 100644 --- a/core/gethwrappers/generated/automation_registry_logic_b_wrapper_2_3/automation_registry_logic_b_wrapper_2_3.go +++ b/core/gethwrappers/generated/automation_registry_logic_b_wrapper_2_3/automation_registry_logic_b_wrapper_2_3.go @@ -46,7 +46,7 @@ type AutomationRegistryBase23BillingOverrides struct { var AutomationRegistryLogicBMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"contractAutomationRegistryLogicC2_3\",\"name\":\"logicC\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contractIERC20Metadata\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"acceptUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"addFunds\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"checkCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"enumAutomationRegistryBase2_3.UpkeepFailureReason\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerData\",\"type\":\"bytes\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"enumAutomationRegistryBase2_3.UpkeepFailureReason\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"enumAutomationRegistryBase2_3.UpkeepFailureReason\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"executeCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"enumAutomationRegistryBase2_3.UpkeepFailureReason\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"pauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"removeBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"billingOverrides\",\"type\":\"tuple\"}],\"name\":\"setBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"setUpkeepCheckData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"}],\"name\":\"setUpkeepGasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"name\":\"setUpkeepOffchainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"simulatePerformUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"unpauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20Metadata\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawERC20Fees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLink\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101806040523480156200001257600080fd5b5060405162005c0e38038062005c0e83398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e051610100516101205161014051610160516154d46200073a60003960008181610182015261022f0152600081816120c5015261226b01526000612b910152600050506000612ec701526000613c3b01526000612fa1015260008181610c4701528181610d0801528181610dd30152612c5201526154d46000f3fe6080604052600436106101805760003560e01c80638765ecbe116100d6578063aed2e9291161007f578063ce7dc5b411610059578063ce7dc5b4146104b1578063f2fde38b146104d1578063f7d334ba146104f157610180565b8063aed2e9291461043a578063b148ab6b14610471578063cd7f71b51461049157610180565b8063948108f7116100b0578063948108f7146103e7578063a72aa27e146103fa578063a86e17811461041a57610180565b80638765ecbe1461037c5780638da5cb5b1461039c5780638dcf0fe7146103c757610180565b806354b7faae1161013857806371fae17f1161011257806371fae17f14610327578063744bfe611461034757806379ba50971461036757610180565b806354b7faae146102b457806368d369d8146102d457806371791aa0146102f457610180565b8063349e8cca11610169578063349e8cca146102205780634ee88d35146102745780635165f2f51461029457610180565b80631a2af011146101c757806329c5efad146101e7575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e8080156101c0573d6000f35b3d6000fd5b005b3480156101d357600080fd5b506101c56101e236600461437c565b610511565b3480156101f357600080fd5b506102076102023660046144f0565b610617565b604051610217949392919061460f565b60405180910390f35b34801561022c57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610217565b34801561028057600080fd5b506101c561028f366004614691565b6108f5565b3480156102a057600080fd5b506101c56102af3660046146dd565b610957565b3480156102c057600080fd5b506101c56102cf3660046146f6565b610b09565b3480156102e057600080fd5b506101c56102ef366004614722565b610d7c565b34801561030057600080fd5b5061031461030f3660046144f0565b611008565b6040516102179796959493929190614763565b34801561033357600080fd5b506101c56103423660046146dd565b61176c565b34801561035357600080fd5b506101c561036236600461437c565b611802565b34801561037357600080fd5b506101c5611c7a565b34801561038857600080fd5b506101c56103973660046146dd565b611d77565b3480156103a857600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff1661024f565b3480156103d357600080fd5b506101c56103e2366004614691565b611f2c565b6101c56103f53660046147b1565b611f81565b34801561040657600080fd5b506101c56104153660046147f9565b612343565b34801561042657600080fd5b506101c561043536600461481e565b612442565b34801561044657600080fd5b5061045a610455366004614691565b612523565b604080519215158352602083019190915201610217565b34801561047d57600080fd5b506101c561048c3660046146dd565b6126ce565b34801561049d57600080fd5b506101c56104ac366004614691565b6128fb565b3480156104bd57600080fd5b506102076104cc366004614898565b6129b2565b3480156104dd57600080fd5b506101c56104ec36600461497a565b612a74565b3480156104fd57600080fd5b5061031461050c3660046146dd565b612a88565b61051a82612ac4565b3373ffffffffffffffffffffffffffffffffffffffff821603610569576040517f8c8728c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff8281169116146106135760008281526006602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915590519091339185917fb1cbb2c4b8480034c27e06da5f096b8233a8fd4497028593a41ff6df79726b3591a45b5050565b60006060600080610626612b79565b600086815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff620100008204811695830195909552660100000000000081048516606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490941660e0820152600290910154909216908201525a9150600080826080015173ffffffffffffffffffffffffffffffffffffffff1663f00e6a2a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561077c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107a091906149a7565b73ffffffffffffffffffffffffffffffffffffffff16601660000160149054906101000a900463ffffffff1663ffffffff16896040516107e091906149c4565b60006040518083038160008787f1925050503d806000811461081e576040519150601f19603f3d011682016040523d82523d6000602084013e610823565b606091505b50915091505a6108339085614a0f565b93508161085c5760006040518060200160405280600081525060079650965096505050506108ec565b808060200190518101906108709190614a77565b90975095508661089c5760006040518060200160405280600081525060049650965096505050506108ec565b60185486517401000000000000000000000000000000000000000090910463ffffffff1610156108e85760006040518060200160405280600081525060059650965096505050506108ec565b5050505b92959194509250565b6108fe83612ac4565b6000838152601d60205260409020610917828483614b5c565b50827f2b72ac786c97e68dbab71023ed6f2bdbfc80ad9bb7808941929229d71b7d5664838360405161094a929190614cc0565b60405180910390a2505050565b61096081612ac4565b600081815260046020908152604091829020825161012081018452815460ff808216151580845261010080840490921615159584019590955262010000820463ffffffff9081169684019690965266010000000000008204861660608401526a010000000000000000000090910473ffffffffffffffffffffffffffffffffffffffff908116608084015260018401546fffffffffffffffffffffffffffffffff811660a085015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08501527c0100000000000000000000000000000000000000000000000000000000900490951660e083015260029092015490931690830152610a9a576040517f1b88a78400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610ad9600283612bea565b5060405182907f7bada562044eb163f6b4003c4553e4e62825344c0418eea087bed5ee05a4745690600090a25050565b610b11612bff565b73ffffffffffffffffffffffffffffffffffffffff8216610b5e576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610b68612c50565b90506000811215610bb4576040517fcf47918100000000000000000000000000000000000000000000000000000000815260006004820152602481018390526044015b60405180910390fd5b80821115610bf8576040517fcf4791810000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610bab565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018490526000917f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610c92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cb69190614cd4565b905080610cef576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f5e110f8bc8a20b65dcc87f224bdf1cc039346e267118bae2739847f07321ffa885604051610d6e91815260200190565b60405180910390a350505050565b610d84612bff565b73ffffffffffffffffffffffffffffffffffffffff8216610dd1576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e56576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610e60612c50565b1215610e98576040517f981bb6a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83166000818152602160205260408082205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919290916370a0823190602401602060405180830381865afa158015610f14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f389190614cef565b610f429190614a0f565b905080821115610f88576040517fcf4791810000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610bab565b610fa973ffffffffffffffffffffffffffffffffffffffff85168484612d1f565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f5e110f8bc8a20b65dcc87f224bdf1cc039346e267118bae2739847f07321ffa884604051610d6e91815260200190565b60006060600080600080600061101c612b79565b60006110278a612df8565b905060006014604051806101200160405290816000820160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160139054906101000a900461ffff1661ffff1661ffff1681526020016000820160159054906101000a900460ff1660ff1660ff1681526020016000820160169054906101000a900460ff161515151581526020016000820160179054906101000a900460ff161515151581526020016000820160189054906101000a900460ff161515151581526020016001820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505090506000600460008d8152602001908152602001600020604051806101200160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900460ff161515151581526020016000820160029054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160069054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600a9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820160009054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681526020016001820160109054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff16815260200160018201601c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505090506000808360a00151156113ea5750506040805160208101825260008082529290910151919a5098506009975089965063ffffffff169450859350839250611760915050565b606083015163ffffffff908116146114345750506040805160208101825260008082529290910151919a5098506001975089965063ffffffff169450859350839250611760915050565b8251156114735750506040805160208101825260008082529290910151919a5098506002975089965063ffffffff169450859350839250611760915050565b61147c84612ea3565b8094508198508299505050506114a18e858786604001518b8b888a6101000151613095565b9050806bffffffffffffffffffffffff168360c001516bffffffffffffffffffffffff1610156115035750506040805160208101825260008082529290910151919a5098506006975089965063ffffffff169450859350839250611760915050565b505060006115128d858e613405565b90505a9750600080836080015173ffffffffffffffffffffffffffffffffffffffff1663f00e6a2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611569573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061158d91906149a7565b73ffffffffffffffffffffffffffffffffffffffff16601660000160149054906101000a900463ffffffff1663ffffffff16846040516115cd91906149c4565b60006040518083038160008787f1925050503d806000811461160b576040519150601f19603f3d011682016040523d82523d6000602084013e611610565b606091505b50915091505a611620908b614a0f565b9950816116a6576018548151780100000000000000000000000000000000000000000000000090910463ffffffff1610156116855750506040805160208101825260008082529390910151929b509950600898505063ffffffff169450611760915050565b604090930151929a50600399505063ffffffff909116955061176092505050565b808060200190518101906116ba9190614a77565b909d509b508c6116f45750506040805160208101825260008082529390910151929b509950600498505063ffffffff169450611760915050565b6018548c517401000000000000000000000000000000000000000090910463ffffffff16101561174e5750506040805160208101825260008082529390910151929b509950600598505063ffffffff169450611760915050565b5050506040015163ffffffff16945050505b92959891949750929550565b6117746135e5565b600081815260046020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055602390915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000001690555182917f97d0ef3f46a56168af653f547bdb6f77ec2b1d7d9bc6ba0193c2b340ec68064a91a250565b60145477010000000000000000000000000000000000000000000000900460ff161561185a576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff167701000000000000000000000000000000000000000000000017905573ffffffffffffffffffffffffffffffffffffffff81166118e9576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600460209081526040808320815161012081018352815460ff8082161515835261010080830490911615158387015263ffffffff620100008304811684870152660100000000000083048116606085015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009093048316608085015260018501546fffffffffffffffffffffffffffffffff811660a08601526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08601527c010000000000000000000000000000000000000000000000000000000090041660e084015260029093015481169282019290925286855260059093529220549091163314611a29576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601554604080517f57e871e7000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff909216916357e871e7916004808201926020929091908290030181865afa158015611a99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abd9190614cef565b816060015163ffffffff161115611b00576040517fff84e5dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526004602090815260408083206001015461010085015173ffffffffffffffffffffffffffffffffffffffff1684526021909252909120547001000000000000000000000000000000009091046bffffffffffffffffffffffff1690611b6b908290614a0f565b6101008301805173ffffffffffffffffffffffffffffffffffffffff908116600090815260216020908152604080832095909555888252600490529290922060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff16905551611bee9116846bffffffffffffffffffffffff8416612d1f565b604080516bffffffffffffffffffffffff8316815273ffffffffffffffffffffffffffffffffffffffff8516602082015285917ff3b5906e5672f3e524854103bcafbbdba80dbdfeca2c35e116127b1060a68318910160405180910390a25050601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff1690555050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611cfb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610bab565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b611d8081612ac4565b600081815260046020908152604091829020825161012081018452815460ff808216158015845261010080840490921615159584019590955262010000820463ffffffff9081169684019690965266010000000000008204861660608401526a010000000000000000000090910473ffffffffffffffffffffffffffffffffffffffff908116608084015260018401546fffffffffffffffffffffffffffffffff811660a085015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08501527c0100000000000000000000000000000000000000000000000000000000900490951660e083015260029092015490931690830152611eba576040517f514b6c2400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055611efc600283613636565b5060405182907f8ab10247ce168c27748e656ecf852b951fcaac790c18106b19aa0ae57a8b741f90600090a25050565b611f3583612ac4565b6000838152601e60205260409020611f4e828483614b5c565b50827f3e8740446213c8a77d40e08f79136ce3f347d13ed270a6ebdf57159e0faf4850838360405161094a929190614cc0565b600082815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff6201000082048116958301959095526601000000000000810485166060830181905273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009092048216608084015260018401546fffffffffffffffffffffffffffffffff811660a08501526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08501527c01000000000000000000000000000000000000000000000000000000009004861660e084015260029093015416928101929092529091146120bd576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3415612159577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681610100015173ffffffffffffffffffffffffffffffffffffffff161461214d576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61215634613642565b91505b818160c001516121699190614d08565b600084815260046020908152604080832060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000006bffffffffffffffffffffffff9687160217905561010085015173ffffffffffffffffffffffffffffffffffffffff16835260219091529020546121f991841690614d2d565b61010082015173ffffffffffffffffffffffffffffffffffffffff16600090815260216020526040812091909155349003612269576101008101516122649073ffffffffffffffffffffffffffffffffffffffff1633306bffffffffffffffffffffffff86166136e4565b6122f9565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0836bffffffffffffffffffffffff166040518263ffffffff1660e01b81526004016000604051808303818588803b1580156122df57600080fd5b505af11580156122f3573d6000803e3d6000fd5b50505050505b6040516bffffffffffffffffffffffff83168152339084907fafd24114486da8ebfc32f3626dada8863652e187461aa74d4bfa7348915062039060200160405180910390a3505050565b6108fc8163ffffffff161080612380575060165463ffffffff78010000000000000000000000000000000000000000000000009091048116908216115b156123b7576040517f14c237fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6123c082612ac4565b60008281526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ffff166201000063ffffffff861690810291909117909155915191825283917fc24c07e655ce79fba8a589778987d3c015bc6af1632bb20cf9182e02a65d972c91015b60405180910390a25050565b61244a6135e5565b6000828152600460205260409020546601000000000000900463ffffffff908116146124a2576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790556023909152902081906124f08282614d51565b905050817fd8a6d79d170a55968079d3a89b960d86b4442aef6aac1d01e644c32b9e38b340826040516124369190614dd8565b60008061252e612b79565b601454760100000000000000000000000000000000000000000000900460ff1615612585576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600085815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615158386015262010000820463ffffffff90811684880181905266010000000000008404821660608601526a010000000000000000000090930473ffffffffffffffffffffffffffffffffffffffff9081166080860181905260018701546fffffffffffffffffffffffffffffffff811660a088015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08801527c0100000000000000000000000000000000000000000000000000000000900490921660e0860152600290950154909416908301528451601f890185900485028101850190955287855290936126c193899089908190840183828082843760009201919091525061374892505050565b9097909650945050505050565b600081815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff6201000082048116958301959095526601000000000000810485166060830181905273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009092048216608084015260018401546fffffffffffffffffffffffffffffffff811660a08501526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08501527c01000000000000000000000000000000000000000000000000000000009004861660e0840152600290930154169281019290925290911461280a576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff163314612867576040517f6352a85300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526005602090815260408083208054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821790935560069094528285208054909216909155905173ffffffffffffffffffffffffffffffffffffffff90911692839186917f5cff4db96bef051785e999f44bfcd21c18823e034fb92dd376e3db4ce0feeb2c91a4505050565b61290483612ac4565b6017547c0100000000000000000000000000000000000000000000000000000000900463ffffffff16811115612966576040517fae7235df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083815260076020526040902061297f828483614b5c565b50827fcba2d5723b2ee59e53a8e8a82a4a7caf4fdfe70e9f7c582950bf7e7a5c24e83d838360405161094a929190614cc0565b600060606000806000634b56a42e60e01b8888886040516024016129d893929190614e0f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050612a618982610617565b929c919b50995090975095505050505050565b612a7c613963565b612a85816139e4565b50565b600060606000806000806000612aad8860405180602001604052806000815250611008565b959e949d50929b5090995097509550909350915050565b60008181526005602052604090205473ffffffffffffffffffffffffffffffffffffffff163314612b21576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020546601000000000000900463ffffffff90811614612a85576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614612be8576040517fb60ac5db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6000612bf68383613ad9565b90505b92915050565b60185473ffffffffffffffffffffffffffffffffffffffff163314612be8576040517fb6dfb7a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166000818152602160205260408082205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919290916370a0823190602401602060405180830381865afa158015612cec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d109190614cef565b612d1a9190614ea5565b905090565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052612df39084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613b28565b505050565b6000818160045b600f811015612e85577fff000000000000000000000000000000000000000000000000000000000000008216838260208110612e3d57612e3d614ec5565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614612e7357506000949350505050565b80612e7d81614ef4565b915050612dff565b5081600f1a6001811115612e9b57612e9b6145a5565b949350505050565b600080600080846040015162ffffff1690506000808263ffffffff161190506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612f30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f549190614f46565b5094509092505050600081131580612f6b57508142105b80612f8c5750828015612f8c5750612f838242614a0f565b8463ffffffff16105b15612f9b576019549650612f9f565b8096505b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561300a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061302e9190614f46565b509450909250505060008113158061304557508142105b806130665750828015613066575061305d8242614a0f565b8463ffffffff16105b1561307557601a549550613079565b8095505b86866130848a613c34565b965096509650505050509193909250565b60008080808960018111156130ac576130ac6145a5565b036130bb575062016b48613110565b60018960018111156130cf576130cf6145a5565b036130de57506201ccf0613110565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008a6080015160016131239190614f96565b6131319060ff166040614faf565b60185461315f906103a49074010000000000000000000000000000000000000000900463ffffffff16614d2d565b6131699190614d2d565b601554604080517fde9ee35e0000000000000000000000000000000000000000000000000000000081528151939450600093849373ffffffffffffffffffffffffffffffffffffffff169263de9ee35e92600480820193918290030181865afa1580156131da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131fe9190614fc6565b90925090508183613210836018614d2d565b61321a9190614faf565b60808f015161322a906001614f96565b6132399060ff166115e0614faf565b6132439190614d2d565b61324d9190614d2d565b6132579085614d2d565b6101008e01516040517f125441400000000000000000000000000000000000000000000000000000000081526004810186905291955073ffffffffffffffffffffffffffffffffffffffff1690631254414090602401602060405180830381865afa1580156132ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132ee9190614cef565b8d6060015161ffff166133019190614faf565b945050505060006133128b86613d25565b60008d815260046020526040902054909150610100900460ff16156133775760008c81526023602090815260409182902082518084018452905463ffffffff811680835264010000000090910462ffffff908116928401928352928501525116908201525b60006133e18c6040518061012001604052808d63ffffffff1681526020018681526020018781526020018c81526020018b81526020018a81526020018973ffffffffffffffffffffffffffffffffffffffff16815260200185815260200160001515815250613ea1565b602081015181519192506133f491614d08565b9d9c50505050505050505050505050565b6060600083600181111561341b5761341b6145a5565b036134e4576000848152600760205260409081902090517f6e04ff0d000000000000000000000000000000000000000000000000000000009161346091602401615085565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915290506135de565b60018360018111156134f8576134f86145a5565b036130de5760008280602001905181019061351391906150fe565b6000868152600760205260409081902090519192507f40691db4000000000000000000000000000000000000000000000000000000009161355891849160240161520e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915291506135de9050565b9392505050565b60175473ffffffffffffffffffffffffffffffffffffffff163314612be8576040517f77c3599200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612bf683836140f6565b60006bffffffffffffffffffffffff8211156136e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610bab565b5090565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526137429085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612d71565b50505050565b601454600090819077010000000000000000000000000000000000000000000000900460ff16156137a5576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16770100000000000000000000000000000000000000000000001790556040517f4585e33b000000000000000000000000000000000000000000000000000000009061381a9085906024016152d9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f79188d1600000000000000000000000000000000000000000000000000000000815290935073ffffffffffffffffffffffffffffffffffffffff8616906379188d16906138ed90879087906004016152ec565b60408051808303816000875af115801561390b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061392f9190615305565b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16905590969095509350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612be8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610bab565b3373ffffffffffffffffffffffffffffffffffffffff821603613a63576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610bab565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000818152600183016020526040812054613b2057508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155612bf9565b506000612bf9565b6000613b8a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166141e99092919063ffffffff16565b805190915015612df35780806020019051810190613ba89190614cd4565b612df3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610bab565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613ca4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cc89190614f46565b50935050925050600082131580613cde57508042105b80613d0e57506000846040015162ffffff16118015613d0e5750613d028142614a0f565b846040015162ffffff16105b15613d1e575050601b5492915050565b5092915050565b60408051608081018252600080825260208083018281528385018381526060850184905273ffffffffffffffffffffffffffffffffffffffff878116855260229093528584208054640100000000810462ffffff1690925263ffffffff82169092527b01000000000000000000000000000000000000000000000000000000810460ff16855285517ffeaf968c00000000000000000000000000000000000000000000000000000000815295519495919484936701000000000000009092049091169163feaf968c9160048083019260a09291908290030181865afa158015613e12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e369190614f46565b50935050925050600082131580613e4c57508042105b80613e7c57506000866040015162ffffff16118015613e7c5750613e708142614a0f565b866040015162ffffff16105b15613e905760018301546060850152613e98565b606084018290525b50505092915050565b60408051608081018252600080825260208201819052918101829052606081019190915260008260e001516000015160ff1690506000846060015161ffff168460600151613eef9190614faf565b90508361010001518015613f025750803a105b15613f0a57503a5b600060128311613f1b576001613f31565b613f26601284614a0f565b613f3190600a615451565b9050600060128410613f44576001613f5a565b613f4f846012614a0f565b613f5a90600a615451565b905060008660a00151876040015188602001518960000151613f7c9190614d2d565b613f869087614faf565b613f909190614d2d565b613f9a9190614faf565b9050613fcc828860e0015160600151613fb39190614faf565b613fbd8584614faf565b613fc7919061545d565b613642565b6bffffffffffffffffffffffff1686526080870151613fef90613fc7908361545d565b6bffffffffffffffffffffffff1660408088019190915260e088015101516000906140289062ffffff16683635c9adc5dea00000614faf565b9050600081633b9aca008a60a001518b60e001516020015163ffffffff168c604001518d600001518b61405b9190614faf565b6140659190614d2d565b61406f9190614faf565b6140799190614faf565b614083919061545d565b61408d9190614d2d565b90506140b0848a60e00151606001516140a69190614faf565b613fbd8784614faf565b6bffffffffffffffffffffffff16602089015260808901516140d690613fc7908361545d565b6bffffffffffffffffffffffff1660608901525050505050505092915050565b600081815260018301602052604081205480156141df57600061411a600183614a0f565b855490915060009061412e90600190614a0f565b905081811461419357600086600001828154811061414e5761414e614ec5565b906000526020600020015490508087600001848154811061417157614171614ec5565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806141a4576141a4615498565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050612bf9565b6000915050612bf9565b6060612e9b8484600085856000808673ffffffffffffffffffffffffffffffffffffffff16858760405161421d91906149c4565b60006040518083038185875af1925050503d806000811461425a576040519150601f19603f3d011682016040523d82523d6000602084013e61425f565b606091505b50915091506142708783838761427b565b979650505050505050565b6060831561431157825160000361430a5773ffffffffffffffffffffffffffffffffffffffff85163b61430a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610bab565b5081612e9b565b612e9b83838151156143265781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bab91906152d9565b73ffffffffffffffffffffffffffffffffffffffff81168114612a8557600080fd5b6000806040838503121561438f57600080fd5b8235915060208301356143a18161435a565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff811182821017156143ff576143ff6143ac565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561444c5761444c6143ac565b604052919050565b600067ffffffffffffffff82111561446e5761446e6143ac565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f8301126144ab57600080fd5b81356144be6144b982614454565b614405565b8181528460208386010111156144d357600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561450357600080fd5b82359150602083013567ffffffffffffffff81111561452157600080fd5b61452d8582860161449a565b9150509250929050565b60005b8381101561455257818101518382015260200161453a565b50506000910152565b60008151808452614573816020860160208601614537565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600a811061460b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b841515815260806020820152600061462a608083018661455b565b905061463960408301856145d4565b82606083015295945050505050565b60008083601f84011261465a57600080fd5b50813567ffffffffffffffff81111561467257600080fd5b60208301915083602082850101111561468a57600080fd5b9250929050565b6000806000604084860312156146a657600080fd5b83359250602084013567ffffffffffffffff8111156146c457600080fd5b6146d086828701614648565b9497909650939450505050565b6000602082840312156146ef57600080fd5b5035919050565b6000806040838503121561470957600080fd5b82356147148161435a565b946020939093013593505050565b60008060006060848603121561473757600080fd5b83356147428161435a565b925060208401356147528161435a565b929592945050506040919091013590565b871515815260e06020820152600061477e60e083018961455b565b905061478d60408301886145d4565b8560608301528460808301528360a08301528260c083015298975050505050505050565b600080604083850312156147c457600080fd5b8235915060208301356bffffffffffffffffffffffff811681146143a157600080fd5b63ffffffff81168114612a8557600080fd5b6000806040838503121561480c57600080fd5b8235915060208301356143a1816147e7565b600080828403606081121561483257600080fd5b8335925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201121561486657600080fd5b506020830190509250929050565b600067ffffffffffffffff82111561488e5761488e6143ac565b5060051b60200190565b600080600080606085870312156148ae57600080fd5b8435935060208086013567ffffffffffffffff808211156148ce57600080fd5b818801915088601f8301126148e257600080fd5b81356148f06144b982614874565b81815260059190911b8301840190848101908b83111561490f57600080fd5b8585015b838110156149475780358581111561492b5760008081fd5b6149398e89838a010161449a565b845250918601918601614913565b5097505050604088013592508083111561496057600080fd5b505061496e87828801614648565b95989497509550505050565b60006020828403121561498c57600080fd5b81356135de8161435a565b80516149a28161435a565b919050565b6000602082840312156149b957600080fd5b81516135de8161435a565b600082516149d6818460208701614537565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115612bf957612bf96149e0565b805180151581146149a257600080fd5b600082601f830112614a4357600080fd5b8151614a516144b982614454565b818152846020838601011115614a6657600080fd5b612e9b826020830160208701614537565b60008060408385031215614a8a57600080fd5b614a9383614a22565b9150602083015167ffffffffffffffff811115614aaf57600080fd5b61452d85828601614a32565b600181811c90821680614acf57607f821691505b602082108103614b08577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f821115612df357600081815260208120601f850160051c81016020861015614b355750805b601f850160051c820191505b81811015614b5457828155600101614b41565b505050505050565b67ffffffffffffffff831115614b7457614b746143ac565b614b8883614b828354614abb565b83614b0e565b6000601f841160018114614bda5760008515614ba45750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355614c70565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015614c295786850135825560209485019460019092019101614c09565b5086821015614c64577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000612e9b602083018486614c77565b600060208284031215614ce657600080fd5b612bf682614a22565b600060208284031215614d0157600080fd5b5051919050565b6bffffffffffffffffffffffff818116838216019080821115613d1e57613d1e6149e0565b80820180821115612bf957612bf96149e0565b62ffffff81168114612a8557600080fd5b8135614d5c816147e7565b63ffffffff811690508154817fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000082161783556020840135614d9c81614d40565b66ffffff000000008160201b16837fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000008416171784555050505050565b604081018235614de7816147e7565b63ffffffff1682526020830135614dfd81614d40565b62ffffff811660208401525092915050565b6000604082016040835280865180835260608501915060608160051b8601019250602080890160005b83811015614e84577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018552614e7286835161455b565b95509382019390820190600101614e38565b505085840381870152505050614e9b818587614c77565b9695505050505050565b8181036000831280158383131683831282161715613d1e57613d1e6149e0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614f2557614f256149e0565b5060010190565b805169ffffffffffffffffffff811681146149a257600080fd5b600080600080600060a08688031215614f5e57600080fd5b614f6786614f2c565b9450602086015193506040860151925060608601519150614f8a60808701614f2c565b90509295509295909350565b60ff8181168382160190811115612bf957612bf96149e0565b8082028115828204841417612bf957612bf96149e0565b60008060408385031215614fd957600080fd5b505080516020909101519092909150565b60008154614ff781614abb565b808552602060018381168015615014576001811461504c5761507a565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838901528284151560051b890101955061507a565b866000528260002060005b858110156150725781548a8201860152908301908401615057565b890184019650505b505050505092915050565b602081526000612bf66020830184614fea565b600082601f8301126150a957600080fd5b815160206150b96144b983614874565b82815260059290921b840181019181810190868411156150d857600080fd5b8286015b848110156150f357805183529183019183016150dc565b509695505050505050565b60006020828403121561511057600080fd5b815167ffffffffffffffff8082111561512857600080fd5b90830190610100828603121561513d57600080fd5b6151456143db565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015261517d60a08401614997565b60a082015260c08301518281111561519457600080fd5b6151a087828601615098565b60c08301525060e0830151828111156151b857600080fd5b6151c487828601614a32565b60e08301525095945050505050565b600081518084526020808501945080840160005b83811015615203578151875295820195908201906001016151e7565b509495945050505050565b60408152825160408201526020830151606082015260408301516080820152606083015160a0820152608083015160c082015273ffffffffffffffffffffffffffffffffffffffff60a08401511660e0820152600060c084015161010080818501525061527f6101408401826151d3565b905060e08501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0848303016101208501526152bb828261455b565b91505082810360208401526152d08185614fea565b95945050505050565b602081526000612bf6602083018461455b565b828152604060208201526000612e9b604083018461455b565b6000806040838503121561531857600080fd5b61532183614a22565b9150602083015190509250929050565b600181815b8085111561538a57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615370576153706149e0565b8085161561537d57918102915b93841c9390800290615336565b509250929050565b6000826153a157506001612bf9565b816153ae57506000612bf9565b81600181146153c457600281146153ce576153ea565b6001915050612bf9565b60ff8411156153df576153df6149e0565b50506001821b612bf9565b5060208310610133831016604e8410600b841016171561540d575081810a612bf9565b6154178383615331565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615449576154496149e0565b029392505050565b6000612bf68383615392565b600082615493577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000813000a", + Bin: "0x6101806040523480156200001257600080fd5b5060405162005c3038038062005c3083398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e051610100516101205161014051610160516154f66200073a60003960008181610182015261022f0152600081816120e7015261228d01526000612bb30152600050506000612ee901526000613c5d01526000612fc3015260008181610c4701528181610d0801528181610dd30152612c7401526154f66000f3fe6080604052600436106101805760003560e01c80638765ecbe116100d6578063aed2e9291161007f578063ce7dc5b411610059578063ce7dc5b4146104b1578063f2fde38b146104d1578063f7d334ba146104f157610180565b8063aed2e9291461043a578063b148ab6b14610471578063cd7f71b51461049157610180565b8063948108f7116100b0578063948108f7146103e7578063a72aa27e146103fa578063a86e17811461041a57610180565b80638765ecbe1461037c5780638da5cb5b1461039c5780638dcf0fe7146103c757610180565b806354b7faae1161013857806371fae17f1161011257806371fae17f14610327578063744bfe611461034757806379ba50971461036757610180565b806354b7faae146102b457806368d369d8146102d457806371791aa0146102f457610180565b8063349e8cca11610169578063349e8cca146102205780634ee88d35146102745780635165f2f51461029457610180565b80631a2af011146101c757806329c5efad146101e7575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e8080156101c0573d6000f35b3d6000fd5b005b3480156101d357600080fd5b506101c56101e236600461439e565b610511565b3480156101f357600080fd5b50610207610202366004614512565b610617565b6040516102179493929190614631565b60405180910390f35b34801561022c57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610217565b34801561028057600080fd5b506101c561028f3660046146b3565b6108f5565b3480156102a057600080fd5b506101c56102af3660046146ff565b610957565b3480156102c057600080fd5b506101c56102cf366004614718565b610b09565b3480156102e057600080fd5b506101c56102ef366004614744565b610d7c565b34801561030057600080fd5b5061031461030f366004614512565b61102a565b6040516102179796959493929190614785565b34801561033357600080fd5b506101c56103423660046146ff565b61178e565b34801561035357600080fd5b506101c561036236600461439e565b611824565b34801561037357600080fd5b506101c5611c9c565b34801561038857600080fd5b506101c56103973660046146ff565b611d99565b3480156103a857600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff1661024f565b3480156103d357600080fd5b506101c56103e23660046146b3565b611f4e565b6101c56103f53660046147d3565b611fa3565b34801561040657600080fd5b506101c561041536600461481b565b612365565b34801561042657600080fd5b506101c5610435366004614840565b612464565b34801561044657600080fd5b5061045a6104553660046146b3565b612545565b604080519215158352602083019190915201610217565b34801561047d57600080fd5b506101c561048c3660046146ff565b6126f0565b34801561049d57600080fd5b506101c56104ac3660046146b3565b61291d565b3480156104bd57600080fd5b506102076104cc3660046148ba565b6129d4565b3480156104dd57600080fd5b506101c56104ec36600461499c565b612a96565b3480156104fd57600080fd5b5061031461050c3660046146ff565b612aaa565b61051a82612ae6565b3373ffffffffffffffffffffffffffffffffffffffff821603610569576040517f8c8728c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff8281169116146106135760008281526006602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915590519091339185917fb1cbb2c4b8480034c27e06da5f096b8233a8fd4497028593a41ff6df79726b3591a45b5050565b60006060600080610626612b9b565b600086815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff620100008204811695830195909552660100000000000081048516606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490941660e0820152600290910154909216908201525a9150600080826080015173ffffffffffffffffffffffffffffffffffffffff1663f00e6a2a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561077c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107a091906149c9565b73ffffffffffffffffffffffffffffffffffffffff16601660000160149054906101000a900463ffffffff1663ffffffff16896040516107e091906149e6565b60006040518083038160008787f1925050503d806000811461081e576040519150601f19603f3d011682016040523d82523d6000602084013e610823565b606091505b50915091505a6108339085614a31565b93508161085c5760006040518060200160405280600081525060079650965096505050506108ec565b808060200190518101906108709190614a99565b90975095508661089c5760006040518060200160405280600081525060049650965096505050506108ec565b60185486517401000000000000000000000000000000000000000090910463ffffffff1610156108e85760006040518060200160405280600081525060059650965096505050506108ec565b5050505b92959194509250565b6108fe83612ae6565b6000838152601d60205260409020610917828483614b7e565b50827f2b72ac786c97e68dbab71023ed6f2bdbfc80ad9bb7808941929229d71b7d5664838360405161094a929190614ce2565b60405180910390a2505050565b61096081612ae6565b600081815260046020908152604091829020825161012081018452815460ff808216151580845261010080840490921615159584019590955262010000820463ffffffff9081169684019690965266010000000000008204861660608401526a010000000000000000000090910473ffffffffffffffffffffffffffffffffffffffff908116608084015260018401546fffffffffffffffffffffffffffffffff811660a085015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08501527c0100000000000000000000000000000000000000000000000000000000900490951660e083015260029092015490931690830152610a9a576040517f1b88a78400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610ad9600283612c0c565b5060405182907f7bada562044eb163f6b4003c4553e4e62825344c0418eea087bed5ee05a4745690600090a25050565b610b11612c21565b73ffffffffffffffffffffffffffffffffffffffff8216610b5e576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610b68612c72565b90506000811215610bb4576040517fcf47918100000000000000000000000000000000000000000000000000000000815260006004820152602481018390526044015b60405180910390fd5b80821115610bf8576040517fcf4791810000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610bab565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018490526000917f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610c92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cb69190614cf6565b905080610cef576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f5e110f8bc8a20b65dcc87f224bdf1cc039346e267118bae2739847f07321ffa885604051610d6e91815260200190565b60405180910390a350505050565b610d84612c21565b73ffffffffffffffffffffffffffffffffffffffff8216610dd1576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e56576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610e60612c72565b128015610e835750600060255460ff166001811115610e8157610e816145c7565b145b15610eba576040517f981bb6a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83166000818152602160205260408082205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919290916370a0823190602401602060405180830381865afa158015610f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5a9190614d11565b610f649190614a31565b905080821115610faa576040517fcf4791810000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610bab565b610fcb73ffffffffffffffffffffffffffffffffffffffff85168484612d41565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f5e110f8bc8a20b65dcc87f224bdf1cc039346e267118bae2739847f07321ffa884604051610d6e91815260200190565b60006060600080600080600061103e612b9b565b60006110498a612e1a565b905060006014604051806101200160405290816000820160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160139054906101000a900461ffff1661ffff1661ffff1681526020016000820160159054906101000a900460ff1660ff1660ff1681526020016000820160169054906101000a900460ff161515151581526020016000820160179054906101000a900460ff161515151581526020016000820160189054906101000a900460ff161515151581526020016001820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505090506000600460008d8152602001908152602001600020604051806101200160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900460ff161515151581526020016000820160029054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160069054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600a9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820160009054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681526020016001820160109054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff16815260200160018201601c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505090506000808360a001511561140c5750506040805160208101825260008082529290910151919a5098506009975089965063ffffffff169450859350839250611782915050565b606083015163ffffffff908116146114565750506040805160208101825260008082529290910151919a5098506001975089965063ffffffff169450859350839250611782915050565b8251156114955750506040805160208101825260008082529290910151919a5098506002975089965063ffffffff169450859350839250611782915050565b61149e84612ec5565b8094508198508299505050506114c38e858786604001518b8b888a61010001516130b7565b9050806bffffffffffffffffffffffff168360c001516bffffffffffffffffffffffff1610156115255750506040805160208101825260008082529290910151919a5098506006975089965063ffffffff169450859350839250611782915050565b505060006115348d858e613427565b90505a9750600080836080015173ffffffffffffffffffffffffffffffffffffffff1663f00e6a2a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561158b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115af91906149c9565b73ffffffffffffffffffffffffffffffffffffffff16601660000160149054906101000a900463ffffffff1663ffffffff16846040516115ef91906149e6565b60006040518083038160008787f1925050503d806000811461162d576040519150601f19603f3d011682016040523d82523d6000602084013e611632565b606091505b50915091505a611642908b614a31565b9950816116c8576018548151780100000000000000000000000000000000000000000000000090910463ffffffff1610156116a75750506040805160208101825260008082529390910151929b509950600898505063ffffffff169450611782915050565b604090930151929a50600399505063ffffffff909116955061178292505050565b808060200190518101906116dc9190614a99565b909d509b508c6117165750506040805160208101825260008082529390910151929b509950600498505063ffffffff169450611782915050565b6018548c517401000000000000000000000000000000000000000090910463ffffffff1610156117705750506040805160208101825260008082529390910151929b509950600598505063ffffffff169450611782915050565b5050506040015163ffffffff16945050505b92959891949750929550565b611796613607565b600081815260046020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055602390915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000001690555182917f97d0ef3f46a56168af653f547bdb6f77ec2b1d7d9bc6ba0193c2b340ec68064a91a250565b60145477010000000000000000000000000000000000000000000000900460ff161561187c576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff167701000000000000000000000000000000000000000000000017905573ffffffffffffffffffffffffffffffffffffffff811661190b576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600460209081526040808320815161012081018352815460ff8082161515835261010080830490911615158387015263ffffffff620100008304811684870152660100000000000083048116606085015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009093048316608085015260018501546fffffffffffffffffffffffffffffffff811660a08601526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08601527c010000000000000000000000000000000000000000000000000000000090041660e084015260029093015481169282019290925286855260059093529220549091163314611a4b576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601554604080517f57e871e7000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff909216916357e871e7916004808201926020929091908290030181865afa158015611abb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611adf9190614d11565b816060015163ffffffff161115611b22576040517fff84e5dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526004602090815260408083206001015461010085015173ffffffffffffffffffffffffffffffffffffffff1684526021909252909120547001000000000000000000000000000000009091046bffffffffffffffffffffffff1690611b8d908290614a31565b6101008301805173ffffffffffffffffffffffffffffffffffffffff908116600090815260216020908152604080832095909555888252600490529290922060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff16905551611c109116846bffffffffffffffffffffffff8416612d41565b604080516bffffffffffffffffffffffff8316815273ffffffffffffffffffffffffffffffffffffffff8516602082015285917ff3b5906e5672f3e524854103bcafbbdba80dbdfeca2c35e116127b1060a68318910160405180910390a25050601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff1690555050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611d1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610bab565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b611da281612ae6565b600081815260046020908152604091829020825161012081018452815460ff808216158015845261010080840490921615159584019590955262010000820463ffffffff9081169684019690965266010000000000008204861660608401526a010000000000000000000090910473ffffffffffffffffffffffffffffffffffffffff908116608084015260018401546fffffffffffffffffffffffffffffffff811660a085015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08501527c0100000000000000000000000000000000000000000000000000000000900490951660e083015260029092015490931690830152611edc576040517f514b6c2400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055611f1e600283613658565b5060405182907f8ab10247ce168c27748e656ecf852b951fcaac790c18106b19aa0ae57a8b741f90600090a25050565b611f5783612ae6565b6000838152601e60205260409020611f70828483614b7e565b50827f3e8740446213c8a77d40e08f79136ce3f347d13ed270a6ebdf57159e0faf4850838360405161094a929190614ce2565b600082815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff6201000082048116958301959095526601000000000000810485166060830181905273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009092048216608084015260018401546fffffffffffffffffffffffffffffffff811660a08501526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08501527c01000000000000000000000000000000000000000000000000000000009004861660e084015260029093015416928101929092529091146120df576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b341561217b577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681610100015173ffffffffffffffffffffffffffffffffffffffff161461216f576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61217834613664565b91505b818160c0015161218b9190614d2a565b600084815260046020908152604080832060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000006bffffffffffffffffffffffff9687160217905561010085015173ffffffffffffffffffffffffffffffffffffffff168352602190915290205461221b91841690614d4f565b61010082015173ffffffffffffffffffffffffffffffffffffffff1660009081526021602052604081209190915534900361228b576101008101516122869073ffffffffffffffffffffffffffffffffffffffff1633306bffffffffffffffffffffffff8616613706565b61231b565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0836bffffffffffffffffffffffff166040518263ffffffff1660e01b81526004016000604051808303818588803b15801561230157600080fd5b505af1158015612315573d6000803e3d6000fd5b50505050505b6040516bffffffffffffffffffffffff83168152339084907fafd24114486da8ebfc32f3626dada8863652e187461aa74d4bfa7348915062039060200160405180910390a3505050565b6108fc8163ffffffff1610806123a2575060165463ffffffff78010000000000000000000000000000000000000000000000009091048116908216115b156123d9576040517f14c237fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6123e282612ae6565b60008281526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ffff166201000063ffffffff861690810291909117909155915191825283917fc24c07e655ce79fba8a589778987d3c015bc6af1632bb20cf9182e02a65d972c91015b60405180910390a25050565b61246c613607565b6000828152600460205260409020546601000000000000900463ffffffff908116146124c4576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790556023909152902081906125128282614d73565b905050817fd8a6d79d170a55968079d3a89b960d86b4442aef6aac1d01e644c32b9e38b340826040516124589190614dfa565b600080612550612b9b565b601454760100000000000000000000000000000000000000000000900460ff16156125a7576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600085815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615158386015262010000820463ffffffff90811684880181905266010000000000008404821660608601526a010000000000000000000090930473ffffffffffffffffffffffffffffffffffffffff9081166080860181905260018701546fffffffffffffffffffffffffffffffff811660a088015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08801527c0100000000000000000000000000000000000000000000000000000000900490921660e0860152600290950154909416908301528451601f890185900485028101850190955287855290936126e393899089908190840183828082843760009201919091525061376a92505050565b9097909650945050505050565b600081815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff6201000082048116958301959095526601000000000000810485166060830181905273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009092048216608084015260018401546fffffffffffffffffffffffffffffffff811660a08501526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08501527c01000000000000000000000000000000000000000000000000000000009004861660e0840152600290930154169281019290925290911461282c576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff163314612889576040517f6352a85300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526005602090815260408083208054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821790935560069094528285208054909216909155905173ffffffffffffffffffffffffffffffffffffffff90911692839186917f5cff4db96bef051785e999f44bfcd21c18823e034fb92dd376e3db4ce0feeb2c91a4505050565b61292683612ae6565b6017547c0100000000000000000000000000000000000000000000000000000000900463ffffffff16811115612988576040517fae7235df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526007602052604090206129a1828483614b7e565b50827fcba2d5723b2ee59e53a8e8a82a4a7caf4fdfe70e9f7c582950bf7e7a5c24e83d838360405161094a929190614ce2565b600060606000806000634b56a42e60e01b8888886040516024016129fa93929190614e31565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050612a838982610617565b929c919b50995090975095505050505050565b612a9e613985565b612aa781613a06565b50565b600060606000806000806000612acf886040518060200160405280600081525061102a565b959e949d50929b5090995097509550909350915050565b60008181526005602052604090205473ffffffffffffffffffffffffffffffffffffffff163314612b43576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020546601000000000000900463ffffffff90811614612aa7576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614612c0a576040517fb60ac5db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6000612c188383613afb565b90505b92915050565b60185473ffffffffffffffffffffffffffffffffffffffff163314612c0a576040517fb6dfb7a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166000818152602160205260408082205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919290916370a0823190602401602060405180830381865afa158015612d0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d329190614d11565b612d3c9190614ec7565b905090565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052612e159084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613b4a565b505050565b6000818160045b600f811015612ea7577fff000000000000000000000000000000000000000000000000000000000000008216838260208110612e5f57612e5f614ee7565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614612e9557506000949350505050565b80612e9f81614f16565b915050612e21565b5081600f1a6001811115612ebd57612ebd6145c7565b949350505050565b600080600080846040015162ffffff1690506000808263ffffffff161190506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612f52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f769190614f68565b5094509092505050600081131580612f8d57508142105b80612fae5750828015612fae5750612fa58242614a31565b8463ffffffff16105b15612fbd576019549650612fc1565b8096505b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561302c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130509190614f68565b509450909250505060008113158061306757508142105b806130885750828015613088575061307f8242614a31565b8463ffffffff16105b1561309757601a54955061309b565b8095505b86866130a68a613c56565b965096509650505050509193909250565b60008080808960018111156130ce576130ce6145c7565b036130dd575062016b48613132565b60018960018111156130f1576130f16145c7565b0361310057506201ccf0613132565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008a6080015160016131459190614fb8565b6131539060ff166040614fd1565b601854613181906103a49074010000000000000000000000000000000000000000900463ffffffff16614d4f565b61318b9190614d4f565b601554604080517fde9ee35e0000000000000000000000000000000000000000000000000000000081528151939450600093849373ffffffffffffffffffffffffffffffffffffffff169263de9ee35e92600480820193918290030181865afa1580156131fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132209190614fe8565b90925090508183613232836018614d4f565b61323c9190614fd1565b60808f015161324c906001614fb8565b61325b9060ff166115e0614fd1565b6132659190614d4f565b61326f9190614d4f565b6132799085614d4f565b6101008e01516040517f125441400000000000000000000000000000000000000000000000000000000081526004810186905291955073ffffffffffffffffffffffffffffffffffffffff1690631254414090602401602060405180830381865afa1580156132ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133109190614d11565b8d6060015161ffff166133239190614fd1565b945050505060006133348b86613d47565b60008d815260046020526040902054909150610100900460ff16156133995760008c81526023602090815260409182902082518084018452905463ffffffff811680835264010000000090910462ffffff908116928401928352928501525116908201525b60006134038c6040518061012001604052808d63ffffffff1681526020018681526020018781526020018c81526020018b81526020018a81526020018973ffffffffffffffffffffffffffffffffffffffff16815260200185815260200160001515815250613ec3565b6020810151815191925061341691614d2a565b9d9c50505050505050505050505050565b6060600083600181111561343d5761343d6145c7565b03613506576000848152600760205260409081902090517f6e04ff0d0000000000000000000000000000000000000000000000000000000091613482916024016150a7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050613600565b600183600181111561351a5761351a6145c7565b03613100576000828060200190518101906135359190615120565b6000868152600760205260409081902090519192507f40691db4000000000000000000000000000000000000000000000000000000009161357a918491602401615230565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915291506136009050565b9392505050565b60175473ffffffffffffffffffffffffffffffffffffffff163314612c0a576040517f77c3599200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612c188383614118565b60006bffffffffffffffffffffffff821115613702576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610bab565b5090565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526137649085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612d93565b50505050565b601454600090819077010000000000000000000000000000000000000000000000900460ff16156137c7576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16770100000000000000000000000000000000000000000000001790556040517f4585e33b000000000000000000000000000000000000000000000000000000009061383c9085906024016152fb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f79188d1600000000000000000000000000000000000000000000000000000000815290935073ffffffffffffffffffffffffffffffffffffffff8616906379188d169061390f908790879060040161530e565b60408051808303816000875af115801561392d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139519190615327565b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16905590969095509350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612c0a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610bab565b3373ffffffffffffffffffffffffffffffffffffffff821603613a85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610bab565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000818152600183016020526040812054613b4257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155612c1b565b506000612c1b565b6000613bac826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661420b9092919063ffffffff16565b805190915015612e155780806020019051810190613bca9190614cf6565b612e15576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610bab565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613cc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cea9190614f68565b50935050925050600082131580613d0057508042105b80613d3057506000846040015162ffffff16118015613d305750613d248142614a31565b846040015162ffffff16105b15613d40575050601b5492915050565b5092915050565b60408051608081018252600080825260208083018281528385018381526060850184905273ffffffffffffffffffffffffffffffffffffffff878116855260229093528584208054640100000000810462ffffff1690925263ffffffff82169092527b01000000000000000000000000000000000000000000000000000000810460ff16855285517ffeaf968c00000000000000000000000000000000000000000000000000000000815295519495919484936701000000000000009092049091169163feaf968c9160048083019260a09291908290030181865afa158015613e34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e589190614f68565b50935050925050600082131580613e6e57508042105b80613e9e57506000866040015162ffffff16118015613e9e5750613e928142614a31565b866040015162ffffff16105b15613eb25760018301546060850152613eba565b606084018290525b50505092915050565b60408051608081018252600080825260208201819052918101829052606081019190915260008260e001516000015160ff1690506000846060015161ffff168460600151613f119190614fd1565b90508361010001518015613f245750803a105b15613f2c57503a5b600060128311613f3d576001613f53565b613f48601284614a31565b613f5390600a615473565b9050600060128410613f66576001613f7c565b613f71846012614a31565b613f7c90600a615473565b905060008660a00151876040015188602001518960000151613f9e9190614d4f565b613fa89087614fd1565b613fb29190614d4f565b613fbc9190614fd1565b9050613fee828860e0015160600151613fd59190614fd1565b613fdf8584614fd1565b613fe9919061547f565b613664565b6bffffffffffffffffffffffff168652608087015161401190613fe9908361547f565b6bffffffffffffffffffffffff1660408088019190915260e0880151015160009061404a9062ffffff16683635c9adc5dea00000614fd1565b9050600081633b9aca008a60a001518b60e001516020015163ffffffff168c604001518d600001518b61407d9190614fd1565b6140879190614d4f565b6140919190614fd1565b61409b9190614fd1565b6140a5919061547f565b6140af9190614d4f565b90506140d2848a60e00151606001516140c89190614fd1565b613fdf8784614fd1565b6bffffffffffffffffffffffff16602089015260808901516140f890613fe9908361547f565b6bffffffffffffffffffffffff1660608901525050505050505092915050565b6000818152600183016020526040812054801561420157600061413c600183614a31565b855490915060009061415090600190614a31565b90508181146141b557600086600001828154811061417057614170614ee7565b906000526020600020015490508087600001848154811061419357614193614ee7565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806141c6576141c66154ba565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050612c1b565b6000915050612c1b565b6060612ebd8484600085856000808673ffffffffffffffffffffffffffffffffffffffff16858760405161423f91906149e6565b60006040518083038185875af1925050503d806000811461427c576040519150601f19603f3d011682016040523d82523d6000602084013e614281565b606091505b50915091506142928783838761429d565b979650505050505050565b6060831561433357825160000361432c5773ffffffffffffffffffffffffffffffffffffffff85163b61432c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610bab565b5081612ebd565b612ebd83838151156143485781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bab91906152fb565b73ffffffffffffffffffffffffffffffffffffffff81168114612aa757600080fd5b600080604083850312156143b157600080fd5b8235915060208301356143c38161437c565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715614421576144216143ce565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561446e5761446e6143ce565b604052919050565b600067ffffffffffffffff821115614490576144906143ce565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f8301126144cd57600080fd5b81356144e06144db82614476565b614427565b8181528460208386010111156144f557600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561452557600080fd5b82359150602083013567ffffffffffffffff81111561454357600080fd5b61454f858286016144bc565b9150509250929050565b60005b8381101561457457818101518382015260200161455c565b50506000910152565b60008151808452614595816020860160208601614559565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600a811061462d577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b841515815260806020820152600061464c608083018661457d565b905061465b60408301856145f6565b82606083015295945050505050565b60008083601f84011261467c57600080fd5b50813567ffffffffffffffff81111561469457600080fd5b6020830191508360208285010111156146ac57600080fd5b9250929050565b6000806000604084860312156146c857600080fd5b83359250602084013567ffffffffffffffff8111156146e657600080fd5b6146f28682870161466a565b9497909650939450505050565b60006020828403121561471157600080fd5b5035919050565b6000806040838503121561472b57600080fd5b82356147368161437c565b946020939093013593505050565b60008060006060848603121561475957600080fd5b83356147648161437c565b925060208401356147748161437c565b929592945050506040919091013590565b871515815260e0602082015260006147a060e083018961457d565b90506147af60408301886145f6565b8560608301528460808301528360a08301528260c083015298975050505050505050565b600080604083850312156147e657600080fd5b8235915060208301356bffffffffffffffffffffffff811681146143c357600080fd5b63ffffffff81168114612aa757600080fd5b6000806040838503121561482e57600080fd5b8235915060208301356143c381614809565b600080828403606081121561485457600080fd5b8335925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201121561488857600080fd5b506020830190509250929050565b600067ffffffffffffffff8211156148b0576148b06143ce565b5060051b60200190565b600080600080606085870312156148d057600080fd5b8435935060208086013567ffffffffffffffff808211156148f057600080fd5b818801915088601f83011261490457600080fd5b81356149126144db82614896565b81815260059190911b8301840190848101908b83111561493157600080fd5b8585015b838110156149695780358581111561494d5760008081fd5b61495b8e89838a01016144bc565b845250918601918601614935565b5097505050604088013592508083111561498257600080fd5b50506149908782880161466a565b95989497509550505050565b6000602082840312156149ae57600080fd5b81356136008161437c565b80516149c48161437c565b919050565b6000602082840312156149db57600080fd5b81516136008161437c565b600082516149f8818460208701614559565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115612c1b57612c1b614a02565b805180151581146149c457600080fd5b600082601f830112614a6557600080fd5b8151614a736144db82614476565b818152846020838601011115614a8857600080fd5b612ebd826020830160208701614559565b60008060408385031215614aac57600080fd5b614ab583614a44565b9150602083015167ffffffffffffffff811115614ad157600080fd5b61454f85828601614a54565b600181811c90821680614af157607f821691505b602082108103614b2a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f821115612e1557600081815260208120601f850160051c81016020861015614b575750805b601f850160051c820191505b81811015614b7657828155600101614b63565b505050505050565b67ffffffffffffffff831115614b9657614b966143ce565b614baa83614ba48354614add565b83614b30565b6000601f841160018114614bfc5760008515614bc65750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355614c92565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015614c4b5786850135825560209485019460019092019101614c2b565b5086821015614c86577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000612ebd602083018486614c99565b600060208284031215614d0857600080fd5b612c1882614a44565b600060208284031215614d2357600080fd5b5051919050565b6bffffffffffffffffffffffff818116838216019080821115613d4057613d40614a02565b80820180821115612c1b57612c1b614a02565b62ffffff81168114612aa757600080fd5b8135614d7e81614809565b63ffffffff811690508154817fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000082161783556020840135614dbe81614d62565b66ffffff000000008160201b16837fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000008416171784555050505050565b604081018235614e0981614809565b63ffffffff1682526020830135614e1f81614d62565b62ffffff811660208401525092915050565b6000604082016040835280865180835260608501915060608160051b8601019250602080890160005b83811015614ea6577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018552614e9486835161457d565b95509382019390820190600101614e5a565b505085840381870152505050614ebd818587614c99565b9695505050505050565b8181036000831280158383131683831282161715613d4057613d40614a02565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614f4757614f47614a02565b5060010190565b805169ffffffffffffffffffff811681146149c457600080fd5b600080600080600060a08688031215614f8057600080fd5b614f8986614f4e565b9450602086015193506040860151925060608601519150614fac60808701614f4e565b90509295509295909350565b60ff8181168382160190811115612c1b57612c1b614a02565b8082028115828204841417612c1b57612c1b614a02565b60008060408385031215614ffb57600080fd5b505080516020909101519092909150565b6000815461501981614add565b808552602060018381168015615036576001811461506e5761509c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838901528284151560051b890101955061509c565b866000528260002060005b858110156150945781548a8201860152908301908401615079565b890184019650505b505050505092915050565b602081526000612c18602083018461500c565b600082601f8301126150cb57600080fd5b815160206150db6144db83614896565b82815260059290921b840181019181810190868411156150fa57600080fd5b8286015b8481101561511557805183529183019183016150fe565b509695505050505050565b60006020828403121561513257600080fd5b815167ffffffffffffffff8082111561514a57600080fd5b90830190610100828603121561515f57600080fd5b6151676143fd565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015261519f60a084016149b9565b60a082015260c0830151828111156151b657600080fd5b6151c2878286016150ba565b60c08301525060e0830151828111156151da57600080fd5b6151e687828601614a54565b60e08301525095945050505050565b600081518084526020808501945080840160005b8381101561522557815187529582019590820190600101615209565b509495945050505050565b60408152825160408201526020830151606082015260408301516080820152606083015160a0820152608083015160c082015273ffffffffffffffffffffffffffffffffffffffff60a08401511660e0820152600060c08401516101008081850152506152a16101408401826151f5565b905060e08501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0848303016101208501526152dd828261457d565b91505082810360208401526152f2818561500c565b95945050505050565b602081526000612c18602083018461457d565b828152604060208201526000612ebd604083018461457d565b6000806040838503121561533a57600080fd5b61534383614a44565b9150602083015190509250929050565b600181815b808511156153ac57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561539257615392614a02565b8085161561539f57918102915b93841c9390800290615358565b509250929050565b6000826153c357506001612c1b565b816153d057506000612c1b565b81600181146153e657600281146153f05761540c565b6001915050612c1b565b60ff84111561540157615401614a02565b50506001821b612c1b565b5060208310610133831016604e8410600b841016171561542f575081810a612c1b565b6154398383615353565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561546b5761546b614a02565b029392505050565b6000612c1883836153b4565b6000826154b5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000813000a", } var AutomationRegistryLogicBABI = AutomationRegistryLogicBMetaData.ABI diff --git a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 9dbf6e87090..37a52ccd949 100644 --- a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -12,7 +12,7 @@ automation_registrar_wrapper2_3: ../../contracts/solc/v0.8.19/AutomationRegistra automation_registry_logic_a_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_2/AutomationRegistryLogicA2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_2/AutomationRegistryLogicA2_2.bin 2f267fb8467a15c587ce4586ac56069f7229344ad3936430d7c7624c0528a171 automation_registry_logic_a_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.bin e8ae5a25765092049f79eb8344db8e572bacb43c6c6e284b3d00f82667c248f7 automation_registry_logic_b_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_2/AutomationRegistryLogicB2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_2/AutomationRegistryLogicB2_2.bin a6d33dfbbfb0ff253eb59a51f4f6d6d4c22ea5ec95aae52d25d49a312b37a22f -automation_registry_logic_b_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_3/AutomationRegistryLogicB2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_3/AutomationRegistryLogicB2_3.bin 2d0f45d2087f6f3c8bfa0a16b26a1c8c1d5c64b89859478c609201535c96eeed +automation_registry_logic_b_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_3/AutomationRegistryLogicB2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_3/AutomationRegistryLogicB2_3.bin f2bb8dc7fdb8b48ba0a0501e3c195676e73d0e56d94c9061edf12830ebbce495 automation_registry_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistry2_2/AutomationRegistry2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistry2_2/AutomationRegistry2_2.bin de60f69878e9b32a291a001c91fc8636544c2cfbd9b507c8c1a4873b602bfb62 automation_registry_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistry2_3/AutomationRegistry2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistry2_3/AutomationRegistry2_3.bin fa9159b9dd36e37209d9805d0fde82f1cba7d0e2674ecc5a7595d48eb40203c4 automation_utils_2_1: ../../contracts/solc/v0.8.16/AutomationUtils2_1/AutomationUtils2_1.abi ../../contracts/solc/v0.8.16/AutomationUtils2_1/AutomationUtils2_1.bin 815b17b63f15d26a0274b962eefad98cdee4ec897ead58688bbb8e2470e585f5 From fe2e8fd21d65c9faee6afa6668b8e12797b957ce Mon Sep 17 00:00:00 2001 From: Ilja Pavlovs Date: Mon, 6 May 2024 02:09:02 +0300 Subject: [PATCH 41/45] VRF-1035: Add retrieval of VRF Wrapper Config in superscripts (#12977) --- core/scripts/vrfv2/testnet/main.go | 13 ++++++++++--- core/scripts/vrfv2/testnet/v2scripts/util.go | 15 +++++++++++---- core/scripts/vrfv2plus/testnet/main.go | 11 +++++++++-- .../vrfv2plus/testnet/v2plusscripts/util.go | 7 +++++++ 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/core/scripts/vrfv2/testnet/main.go b/core/scripts/vrfv2/testnet/main.go index 88f4d9e0f73..c0e62af781d 100644 --- a/core/scripts/vrfv2/testnet/main.go +++ b/core/scripts/vrfv2/testnet/main.go @@ -12,9 +12,6 @@ import ( "strings" "sync" - "github.com/smartcontractkit/chainlink/core/scripts/vrfv2/testnet/v2scripts" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_owner_test_consumer" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -22,6 +19,9 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/shopspring/decimal" + "github.com/smartcontractkit/chainlink/core/scripts/vrfv2/testnet/v2scripts" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_owner_test_consumer" + "github.com/jmoiron/sqlx" helpers "github.com/smartcontractkit/chainlink/core/scripts/common" @@ -1294,6 +1294,13 @@ func main() { *wrapperPremiumPercentage, *keyHash, *maxNumWords) + case "wrapper-get-config": + cmd := flag.NewFlagSet("wrapper-get-config", flag.ExitOnError) + wrapperAddress := cmd.String("wrapper-address", "", "wrapper address") + helpers.ParseArgs(cmd, os.Args[2:], "wrapper-address") + wrapper, err := vrfv2_wrapper.NewVRFV2Wrapper(common.HexToAddress(*wrapperAddress), e.Ec) + helpers.PanicErr(err) + v2scripts.PrintWrapperConfig(wrapper) case "wrapper-get-fulfillment-tx-size": cmd := flag.NewFlagSet("wrapper-get-fulfillment-tx-size", flag.ExitOnError) wrapperAddress := cmd.String("wrapper-address", "", "address of the VRFV2Wrapper contract") diff --git a/core/scripts/vrfv2/testnet/v2scripts/util.go b/core/scripts/vrfv2/testnet/v2scripts/util.go index 325ced2ab21..2f6e7df23ec 100644 --- a/core/scripts/vrfv2/testnet/v2scripts/util.go +++ b/core/scripts/vrfv2/testnet/v2scripts/util.go @@ -7,14 +7,14 @@ import ( "fmt" "math/big" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_test_v2" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_load_test_with_metrics" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_test_v2" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_load_test_with_metrics" + helpers "github.com/smartcontractkit/chainlink/core/scripts/common" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_blockhash_store" @@ -208,6 +208,13 @@ func WrapperConfigure( helpers.ConfirmTXMined(context.Background(), e.Ec, tx, e.ChainID) } +func PrintWrapperConfig(wrapper *vrfv2_wrapper.VRFV2Wrapper) { + cfg, err := wrapper.GetConfig(nil) + helpers.PanicErr(err) + fmt.Printf("Wrapper config: %+v\n", cfg) + fmt.Printf("Wrapper Keyhash: %s\n", fmt.Sprintf("0x%x", cfg.KeyHash)) +} + func WrapperConsumerDeploy( e helpers.Environment, link, wrapper common.Address, diff --git a/core/scripts/vrfv2plus/testnet/main.go b/core/scripts/vrfv2plus/testnet/main.go index c2e6a710858..7b47a2f8529 100644 --- a/core/scripts/vrfv2plus/testnet/main.go +++ b/core/scripts/vrfv2plus/testnet/main.go @@ -11,6 +11,8 @@ import ( "os" "strings" + "github.com/ethereum/go-ethereum" + "github.com/smartcontractkit/chainlink/core/scripts/vrfv2plus/testnet/v2plusscripts" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/chain_specific_util_helper" @@ -18,7 +20,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2plus_interface" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_load_test_with_metrics" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -1234,7 +1235,13 @@ func main() { uint32(*stalenessSeconds), uint32(*fulfillmentFlatFeeNativePPM), uint32(*fulfillmentFlatFeeLinkDiscountPPM)) - + case "wrapper-get-config": + cmd := flag.NewFlagSet("wrapper-get-config", flag.ExitOnError) + wrapperAddress := cmd.String("wrapper-address", "", "wrapper address") + helpers.ParseArgs(cmd, os.Args[2:], "wrapper-address") + wrapper, err := vrfv2plus_wrapper.NewVRFV2PlusWrapper(common.HexToAddress(*wrapperAddress), e.Ec) + helpers.PanicErr(err) + v2plusscripts.PrintWrapperConfig(wrapper) case "wrapper-get-fulfillment-tx-size": cmd := flag.NewFlagSet("wrapper-get-fulfillment-tx-size", flag.ExitOnError) wrapperAddress := cmd.String("wrapper-address", "", "address of the VRFV2Wrapper contract") diff --git a/core/scripts/vrfv2plus/testnet/v2plusscripts/util.go b/core/scripts/vrfv2plus/testnet/v2plusscripts/util.go index 6fbdc88b869..3d511605811 100644 --- a/core/scripts/vrfv2plus/testnet/v2plusscripts/util.go +++ b/core/scripts/vrfv2plus/testnet/v2plusscripts/util.go @@ -287,6 +287,13 @@ func WrapperConfigure( helpers.ConfirmTXMined(context.Background(), e.Ec, tx, e.ChainID) } +func PrintWrapperConfig(wrapper *vrfv2plus_wrapper.VRFV2PlusWrapper) { + cfg, err := wrapper.GetConfig(nil) + helpers.PanicErr(err) + fmt.Printf("Wrapper config: %+v\n", cfg) + fmt.Printf("Wrapper Keyhash: %s\n", fmt.Sprintf("0x%x", cfg.KeyHash)) +} + func WrapperConsumerDeploy( e helpers.Environment, link, wrapper common.Address, From 36cc95f6256b5ba418a916de2c9dc9597508147a Mon Sep 17 00:00:00 2001 From: Christopher Dimitri Sastropranoto Date: Mon, 6 May 2024 17:17:03 +0700 Subject: [PATCH 42/45] KSI-165: Implement update nodes (#13080) * implement update nodes * address PR feedback * regen go wrappers --- .changeset/modern-trainers-hear.md | 5 + contracts/.changeset/three-hotels-agree.md | 5 + .../src/v0.8/keystone/CapabilityRegistry.sol | 46 ++++- .../CapabilityRegistry_AddNodesTest.t.sol | 47 ++++- .../CapabilityRegistry_UpdateNodesTest.t.sol | 195 ++++++++++++++++++ .../keystone_capability_registry.go | 149 ++++++++++++- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 7 files changed, 444 insertions(+), 5 deletions(-) create mode 100644 .changeset/modern-trainers-hear.md create mode 100644 contracts/.changeset/three-hotels-agree.md create mode 100644 contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateNodesTest.t.sol diff --git a/.changeset/modern-trainers-hear.md b/.changeset/modern-trainers-hear.md new file mode 100644 index 00000000000..08f7ab0988a --- /dev/null +++ b/.changeset/modern-trainers-hear.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal Generate gethwrappers for capability registry changes diff --git a/contracts/.changeset/three-hotels-agree.md b/contracts/.changeset/three-hotels-agree.md new file mode 100644 index 00000000000..66ed4b2377e --- /dev/null +++ b/contracts/.changeset/three-hotels-agree.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +Add function to update nodes in capability registry diff --git a/contracts/src/v0.8/keystone/CapabilityRegistry.sol b/contracts/src/v0.8/keystone/CapabilityRegistry.sol index 9e0a67434fc..6ac4caedf50 100644 --- a/contracts/src/v0.8/keystone/CapabilityRegistry.sol +++ b/contracts/src/v0.8/keystone/CapabilityRegistry.sol @@ -106,6 +106,16 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { /// @param nodeOperatorId The ID of the node operator that manages this node event NodeAdded(bytes32 p2pId, uint256 nodeOperatorId); + /// @notice This event is emitted when a node is updated + /// @param p2pId The P2P ID of the node + /// @param nodeOperatorId The ID of the node operator that manages this node + /// @param signer The node's signer address + event NodeUpdated(bytes32 p2pId, uint256 nodeOperatorId, address signer); + + /// @notice This error is thrown when trying to set the node's + /// signer address to zero + error InvalidNodeSigner(); + /// @notice This error is thrown when trying add a capability that already /// exists. error CapabilityAlreadyExists(); @@ -236,12 +246,16 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { for (uint256 i; i < nodes.length; ++i) { Node memory node = nodes[i]; + bool isOwner = msg.sender == owner(); + NodeOperator memory nodeOperator = s_nodeOperators[node.nodeOperatorId]; - if (msg.sender != nodeOperator.admin) revert AccessForbidden(); + if (!isOwner && msg.sender != nodeOperator.admin) revert AccessForbidden(); bool nodeExists = s_nodes[node.p2pId].supportedHashedCapabilityIds.length > 0; if (nodeExists || bytes32(node.p2pId) == bytes32("")) revert InvalidNodeP2PId(node.p2pId); + if (node.signer == address(0)) revert InvalidNodeSigner(); + if (node.supportedHashedCapabilityIds.length == 0) revert InvalidNodeCapabilities(node.supportedHashedCapabilityIds); @@ -255,6 +269,36 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { } } + /// @notice Updates nodes. The node admin can update the node's signer address + /// and reconfigure its supported capabilities + /// @param nodes The nodes to update + function updateNodes(Node[] calldata nodes) external { + for (uint256 i; i < nodes.length; ++i) { + Node memory node = nodes[i]; + + bool isOwner = msg.sender == owner(); + + NodeOperator memory nodeOperator = s_nodeOperators[node.nodeOperatorId]; + if (!isOwner && msg.sender != nodeOperator.admin) revert AccessForbidden(); + + bool nodeExists = s_nodes[node.p2pId].supportedHashedCapabilityIds.length > 0; + if (!nodeExists) revert InvalidNodeP2PId(node.p2pId); + + if (node.signer == address(0)) revert InvalidNodeSigner(); + + if (node.supportedHashedCapabilityIds.length == 0) + revert InvalidNodeCapabilities(node.supportedHashedCapabilityIds); + + for (uint256 j; j < node.supportedHashedCapabilityIds.length; ++j) { + if (!s_hashedCapabilityIds.contains(node.supportedHashedCapabilityIds[j])) + revert InvalidNodeCapabilities(node.supportedHashedCapabilityIds); + } + + s_nodes[node.p2pId] = node; + emit NodeUpdated(node.p2pId, node.nodeOperatorId, node.signer); + } + } + /// @notice Gets a node's data /// @param p2pId The P2P ID of the node to query for /// @return Node The node data diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol index e179cc5cea6..9174e4ed0d3 100644 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodesTest.t.sol @@ -18,7 +18,7 @@ contract CapabilityRegistry_AddNodesTest is BaseTest { s_capabilityRegistry.addCapability(s_capabilityWithConfigurationContract); } - function test_RevertWhen_CalledByNonNodeOperatorAdmin() public { + function test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() public { changePrank(STRANGER); CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); @@ -36,6 +36,24 @@ contract CapabilityRegistry_AddNodesTest is BaseTest { s_capabilityRegistry.addNodes(nodes); } + function test_RevertWhen_SignerAddressEmpty() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: address(0), + supportedHashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeSigner.selector)); + s_capabilityRegistry.addNodes(nodes); + } + function test_RevertWhen_AddingDuplicateP2PId() public { changePrank(NODE_OPERATOR_ONE_ADMIN); CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); @@ -133,4 +151,31 @@ contract CapabilityRegistry_AddNodesTest is BaseTest { assertEq(node.supportedHashedCapabilityIds[0], s_basicHashedCapabilityId); assertEq(node.supportedHashedCapabilityIds[1], s_capabilityWithConfigurationContractId); } + + function test_OwnerCanAddNodes() public { + changePrank(ADMIN); + + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + bytes32[] memory hashedCapabilityIds = new bytes32[](2); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + supportedHashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectEmit(address(s_capabilityRegistry)); + emit NodeAdded(P2P_ID, TEST_NODE_OPERATOR_ONE_ID); + s_capabilityRegistry.addNodes(nodes); + + CapabilityRegistry.Node memory node = s_capabilityRegistry.getNode(P2P_ID); + assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); + assertEq(node.p2pId, P2P_ID); + assertEq(node.supportedHashedCapabilityIds.length, 2); + assertEq(node.supportedHashedCapabilityIds[0], s_basicHashedCapabilityId); + assertEq(node.supportedHashedCapabilityIds[1], s_capabilityWithConfigurationContractId); + } } diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateNodesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateNodesTest.t.sol new file mode 100644 index 00000000000..7ccbd14dbf2 --- /dev/null +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_UpdateNodesTest.t.sol @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilityRegistry} from "../CapabilityRegistry.sol"; + +contract CapabilityRegistry_UpdateNodesTest is BaseTest { + event NodeUpdated(bytes32 p2pId, uint256 nodeOperatorId, address signer); + + uint256 private constant TEST_NODE_OPERATOR_ONE_ID = 0; + uint256 private constant TEST_NODE_OPERATOR_TWO_ID = 1; + bytes32 private constant INVALID_P2P_ID = bytes32("fake-p2p"); + + function setUp() public override { + BaseTest.setUp(); + changePrank(ADMIN); + s_capabilityRegistry.addNodeOperators(_getNodeOperators()); + s_capabilityRegistry.addCapability(s_basicCapability); + s_capabilityRegistry.addCapability(s_capabilityWithConfigurationContract); + + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + bytes32[] memory hashedCapabilityIds = new bytes32[](2); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + supportedHashedCapabilityIds: hashedCapabilityIds + }); + + changePrank(NODE_OPERATOR_ONE_ADMIN); + + s_capabilityRegistry.addNodes(nodes); + } + + function test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() public { + changePrank(STRANGER); + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + supportedHashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(CapabilityRegistry.AccessForbidden.selector); + s_capabilityRegistry.updateNodes(nodes); + } + + function test_RevertWhen_NodeDoesNotExist() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: INVALID_P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + supportedHashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeP2PId.selector, INVALID_P2P_ID)); + s_capabilityRegistry.updateNodes(nodes); + } + + function test_RevertWhen_P2PIDEmpty() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: bytes32(""), + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + supportedHashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeP2PId.selector, bytes32(""))); + s_capabilityRegistry.updateNodes(nodes); + } + + function test_RevertWhen_SignerAddressEmpty() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: address(0), + supportedHashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeSigner.selector)); + s_capabilityRegistry.updateNodes(nodes); + } + + function test_RevertWhen_UpdatingNodeWithoutCapabilities() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](0); + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + supportedHashedCapabilityIds: hashedCapabilityIds + }); + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); + s_capabilityRegistry.updateNodes(nodes); + } + + function test_RevertWhen_AddingNodeWithInvalidCapability() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_nonExistentHashedCapabilityId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + supportedHashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilityRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); + s_capabilityRegistry.updateNodes(nodes); + } + + function test_UpdatesNode() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + supportedHashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectEmit(address(s_capabilityRegistry)); + emit NodeUpdated(P2P_ID, TEST_NODE_OPERATOR_ONE_ID, NODE_OPERATOR_TWO_SIGNER_ADDRESS); + s_capabilityRegistry.updateNodes(nodes); + + CapabilityRegistry.Node memory node = s_capabilityRegistry.getNode(P2P_ID); + assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); + assertEq(node.p2pId, P2P_ID); + assertEq(node.signer, NODE_OPERATOR_TWO_SIGNER_ADDRESS); + assertEq(node.supportedHashedCapabilityIds.length, 1); + assertEq(node.supportedHashedCapabilityIds[0], s_basicHashedCapabilityId); + } + + function test_OwnerCanUpdateNodes() public { + changePrank(ADMIN); + + CapabilityRegistry.Node[] memory nodes = new CapabilityRegistry.Node[](1); + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilityRegistry.Node({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + supportedHashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectEmit(address(s_capabilityRegistry)); + emit NodeUpdated(P2P_ID, TEST_NODE_OPERATOR_ONE_ID, NODE_OPERATOR_TWO_SIGNER_ADDRESS); + s_capabilityRegistry.updateNodes(nodes); + + CapabilityRegistry.Node memory node = s_capabilityRegistry.getNode(P2P_ID); + assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); + assertEq(node.p2pId, P2P_ID); + assertEq(node.signer, NODE_OPERATOR_TWO_SIGNER_ADDRESS); + assertEq(node.supportedHashedCapabilityIds.length, 1); + assertEq(node.supportedHashedCapabilityIds[0], s_basicHashedCapabilityId); + } +} diff --git a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go index 8ea5e29d99c..9080fbd7807 100644 --- a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go +++ b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go @@ -50,8 +50,8 @@ type CapabilityRegistryNodeOperator struct { } var CapabilityRegistryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAlreadyDeprecated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"name\":\"InvalidNodeCapabilities\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"InvalidNodeP2PId\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"lengthOne\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lengthTwo\",\"type\":\"uint256\"}],\"name\":\"LengthMismatch\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDeprecated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedHashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"addNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"deprecateCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilities\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedId\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getHashedCapabilityId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"getNode\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedHashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"isCapabilityDeprecated\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"updateNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60806040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000a5565b50505062000150565b336001600160a01b03821603620000ff5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61214580620001606000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c806365c14dc711610097578063ae3c241c11610066578063ae3c241c14610292578063c2d483a1146102a5578063ddbe4f82146102b8578063f2fde38b146102cd57600080fd5b806365c14dc71461022257806379ba5097146102425780638da5cb5b1461024a5780639cb7c5f41461027257600080fd5b80631cdf6343116100d35780631cdf63431461019457806336b402fb146101a7578063398f3773146101ef57806350c946fe1461020257600080fd5b80630c5801e314610105578063117392ce1461011a578063125700111461012d578063181f5a7714610155575b600080fd5b6101186101133660046116ec565b6102e0565b005b610118610128366004611758565b6105f1565b61014061013b366004611770565b61083c565b60405190151581526020015b60405180910390f35b604080518082018252601881527f4361706162696c697479526567697374727920312e302e3000000000000000006020820152905161014c91906117ed565b6101186101a2366004611800565b61084f565b6101e16101b5366004611842565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b60405190815260200161014c565b6101186101fd366004611800565b610912565b610215610210366004611770565b610aab565b60405161014c9190611864565b610235610230366004611770565b610b73565b60405161014c91906118ea565b610118610c50565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b610285610280366004611770565b610d4d565b60405161014c91906119cc565b6101186102a0366004611770565b610df7565b6101186102b3366004611800565b610ec2565b6102c061124c565b60405161014c91906119da565b6101186102db366004611a4a565b611391565b828114610328576040517fab8b67c600000000000000000000000000000000000000000000000000000000815260048101849052602481018290526044015b60405180910390fd5b6000805473ffffffffffffffffffffffffffffffffffffffff16905b848110156105e957600086868381811061036057610360611a67565b905060200201359050600085858481811061037d5761037d611a67565b905060200281019061038f9190611a96565b61039890611b9e565b805190915073ffffffffffffffffffffffffffffffffffffffff166103e9576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16331480159061042657503373ffffffffffffffffffffffffffffffffffffffff851614155b1561045d576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160008381526007602052604090205473ffffffffffffffffffffffffffffffffffffffff908116911614158061050f57506020808201516040516104a392016117ed565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206000868152600783529290922091926104f6926001019101611cb7565b6040516020818303038152906040528051906020012014155b156105d6578051600083815260076020908152604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90931692909217825582015160019091019061057c9082611da6565b50806000015173ffffffffffffffffffffffffffffffffffffffff167f14c8f513e8a6d86d2d16b0cb64976de4e72386c4f8068eca3b7354373f8fe97a8383602001516040516105cd929190611ec0565b60405180910390a25b5050806105e290611f08565b9050610344565b505050505050565b6105f96113a5565b604080518235602082810191909152808401358284015282518083038401815260609092019092528051910120610631600382611428565b15610668576040517fe288638f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061067a6080840160608501611a4a565b73ffffffffffffffffffffffffffffffffffffffff16146107e5576106a56080830160608401611a4a565b73ffffffffffffffffffffffffffffffffffffffff163b158061078557506106d36080830160608401611a4a565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f884efe6100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff91909116906301ffc9a790602401602060405180830381865afa15801561075f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107839190611f40565b155b156107e55761079a6080830160608401611a4a565b6040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161031f565b6107f0600382611443565b506000818152600260205260409020829061080b8282611f62565b505060405181907f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff0690600090a25050565b6000610849600583611428565b92915050565b6108576113a5565b60005b8181101561090d57600083838381811061087657610876611a67565b60209081029290920135600081815260079093526040832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559093509190506108c76001830182611606565b50506040518181527f1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f9060200160405180910390a15061090681611f08565b905061085a565b505050565b61091a6113a5565b60005b8181101561090d57600083838381811061093957610939611a67565b905060200281019061094b9190611a96565b61095490611b9e565b805190915073ffffffffffffffffffffffffffffffffffffffff166109a5576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600954604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526007909252939020825181547fffffffffffffffffffffffff000000000000000000000000000000000000000016921691909117815591519091906001820190610a289082611da6565b50905050600960008154610a3b90611f08565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b91610a9091859190611ec0565b60405180910390a2505080610aa490611f08565b905061091d565b6040805160808101825260008082526020820181905291810191909152606080820152600082815260086020908152604091829020825160808101845281548152600182015481840152600282015473ffffffffffffffffffffffffffffffffffffffff16818501526003820180548551818602810186019096528086529194929360608601939290830182828015610b6357602002820191906000526020600020905b815481526020019060010190808311610b4f575b5050505050815250509050919050565b6040805180820190915260008152606060208201526000828152600760209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610bd090611c6a565b80601f0160208091040260200160405190810160405280929190818152602001828054610bfc90611c6a565b8015610b635780601f10610c1e57610100808354040283529160200191610b63565b820191906000526020600020905b815481529060010190602001808311610c2c57505050919092525091949350505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610cd1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161031f565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b604080516080808201835260008083526020808401829052838501829052606084018290528582526002808252918590208551938401865280548452600180820154928501929092529182015493949293919284019160ff1690811115610db657610db661192d565b6001811115610dc757610dc761192d565b815260029190910154610100900473ffffffffffffffffffffffffffffffffffffffff1660209091015292915050565b610dff6113a5565b610e0a600382611428565b610e43576040517fe181733f0000000000000000000000000000000000000000000000000000000081526004810182905260240161031f565b610e4e600582611428565b15610e88576040517f16950d1d0000000000000000000000000000000000000000000000000000000081526004810182905260240161031f565b610e93600582611443565b5060405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf2190600090a250565b60005b8181101561090d576000838383818110610ee157610ee1611a67565b9050602002810190610ef39190611fe4565b610efc90612018565b805160009081526007602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff168252600181018054959650939491939092840191610f4c90611c6a565b80601f0160208091040260200160405190810160405280929190818152602001828054610f7890611c6a565b8015610fc55780601f10610f9a57610100808354040283529160200191610fc5565b820191906000526020600020905b815481529060010190602001808311610fa857829003601f168201915b5050505050815250509050806000015173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611039576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020808301516000908152600890915260409020600301541515808061106157506020830151155b156110a05782602001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161031f91815260200190565b8260600151516000036110e55782606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161031f91906120ed565b60005b836060015151811015611172576111268460600151828151811061110e5761110e611a67565b6020026020010151600361142890919063ffffffff16565b6111625783606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161031f91906120ed565b61116b81611f08565b90506110e8565b506020838101805160009081526008835260409081902086518155915160018301558501516002820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9092169190911790556060850151805186936111f7926003850192910190611640565b505050602083810151845160408051928352928201527f5bfe8a52ad26ac6ee7b0cd46d2fd92be04735a31c45ef8aa3d4b7ea1b61bbc1f910160405180910390a15050508061124590611f08565b9050610ec5565b6060600061125a600361144f565b90506000611268600561145c565b82516112749190612125565b67ffffffffffffffff81111561128c5761128c611ad4565b6040519080825280602002602001820160405280156112fc57816020015b6040805160808101825260008082526020808301829052928201819052606082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816112aa5790505b5090506000805b835181101561138857600084828151811061132057611320611a67565b6020026020010151905061133e81600561142890919063ffffffff16565b6113775761134b81610d4d565b84848151811061135d5761135d611a67565b6020026020010181905250828061137390611f08565b9350505b5061138181611f08565b9050611303565b50909392505050565b6113996113a5565b6113a281611466565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314611426576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161031f565b565b600081815260018301602052604081205415155b9392505050565b600061143c838361155b565b6060600061143c836115aa565b6000610849825490565b3373ffffffffffffffffffffffffffffffffffffffff8216036114e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161031f565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120546115a257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610849565b506000610849565b6060816000018054806020026020016040519081016040528092919081815260200182805480156115fa57602002820191906000526020600020905b8154815260200190600101908083116115e6575b50505050509050919050565b50805461161290611c6a565b6000825580601f10611622575050565b601f0160209004906000526020600020908101906113a2919061168b565b82805482825590600052602060002090810192821561167b579160200282015b8281111561167b578251825591602001919060010190611660565b5061168792915061168b565b5090565b5b80821115611687576000815560010161168c565b60008083601f8401126116b257600080fd5b50813567ffffffffffffffff8111156116ca57600080fd5b6020830191508360208260051b85010111156116e557600080fd5b9250929050565b6000806000806040858703121561170257600080fd5b843567ffffffffffffffff8082111561171a57600080fd5b611726888389016116a0565b9096509450602087013591508082111561173f57600080fd5b5061174c878288016116a0565b95989497509550505050565b60006080828403121561176a57600080fd5b50919050565b60006020828403121561178257600080fd5b5035919050565b6000815180845260005b818110156117af57602081850181015186830182015201611793565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061143c6020830184611789565b6000806020838503121561181357600080fd5b823567ffffffffffffffff81111561182a57600080fd5b611836858286016116a0565b90969095509350505050565b6000806040838503121561185557600080fd5b50508035926020909101359150565b6000602080835260a0830184518285015281850151604085015273ffffffffffffffffffffffffffffffffffffffff6040860151166060850152606085015160808086015281815180845260c0870191508483019350600092505b808310156118df57835182529284019260019290920191908401906118bf565b509695505050505050565b6020815273ffffffffffffffffffffffffffffffffffffffff8251166020820152600060208301516040808401526119256060840182611789565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b80518252602081015160208301526040810151600281106119a6577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b604083015260609081015173ffffffffffffffffffffffffffffffffffffffff16910152565b60808101610849828461195c565b6020808252825182820181905260009190848201906040850190845b81811015611a1c57611a0983855161195c565b92840192608092909201916001016119f6565b50909695505050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146113a257600080fd5b600060208284031215611a5c57600080fd5b813561143c81611a28565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112611aca57600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611b2657611b26611ad4565b60405290565b6040516080810167ffffffffffffffff81118282101715611b2657611b26611ad4565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611b9657611b96611ad4565b604052919050565b600060408236031215611bb057600080fd5b611bb8611b03565b8235611bc381611a28565b815260208381013567ffffffffffffffff80821115611be157600080fd5b9085019036601f830112611bf457600080fd5b813581811115611c0657611c06611ad4565b611c36847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611b4f565b91508082523684828501011115611c4c57600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c90821680611c7e57607f821691505b60208210810361176a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454611ccb81611c6a565b80848701526040600180841660008114611cec5760018114611d2457611d52565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a01019550611d52565b896000528660002060005b85811015611d4a5781548b8201860152908301908801611d2f565b8a0184019650505b509398975050505050505050565b601f82111561090d57600081815260208120601f850160051c81016020861015611d875750805b601f850160051c820191505b818110156105e957828155600101611d93565b815167ffffffffffffffff811115611dc057611dc0611ad4565b611dd481611dce8454611c6a565b84611d60565b602080601f831160018114611e275760008415611df15750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556105e9565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015611e7457888601518255948401946001909101908401611e55565b5085821015611eb057878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8281526040602082015260006119256040830184611789565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611f3957611f39611ed9565b5060010190565b600060208284031215611f5257600080fd5b8151801515811461143c57600080fd5b813581556020820135600182015560028101604083013560028110611f8657600080fd5b81546060850135611f9681611a28565b74ffffffffffffffffffffffffffffffffffffffff008160081b1660ff84167fffffffffffffffffffffff000000000000000000000000000000000000000000841617178455505050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112611aca57600080fd5b60006080823603121561202a57600080fd5b612032611b2c565b8235815260208084013581830152604084013561204e81611a28565b6040830152606084013567ffffffffffffffff8082111561206e57600080fd5b9085019036601f83011261208157600080fd5b81358181111561209357612093611ad4565b8060051b91506120a4848301611b4f565b81815291830184019184810190368411156120be57600080fd5b938501935b838510156120dc578435825293850193908501906120c3565b606087015250939695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015611a1c57835183529284019291840191600101612109565b8181038181111561084957610849611ed956fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAlreadyDeprecated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"name\":\"InvalidNodeCapabilities\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"InvalidNodeP2PId\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"lengthOne\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lengthTwo\",\"type\":\"uint256\"}],\"name\":\"LengthMismatch\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDeprecated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"NodeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedHashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"addNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"deprecateCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilities\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedId\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"enumCapabilityRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilityRegistry.Capability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"labelledName\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getHashedCapabilityId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"getNode\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedHashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"isCapabilityDeprecated\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilityRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"updateNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nodeOperatorId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"supportedHashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilityRegistry.Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"updateNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60806040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000a5565b50505062000150565b336001600160a01b03821603620000ff5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6125e680620001606000396000f3fe608060405234801561001057600080fd5b506004361061011b5760003560e01c806365c14dc7116100b2578063ae3c241c11610081578063c2d483a111610066578063c2d483a1146102d3578063ddbe4f82146102e6578063f2fde38b146102fb57600080fd5b8063ae3c241c146102ad578063b38e51f6146102c057600080fd5b806365c14dc71461023d57806379ba50971461025d5780638da5cb5b146102655780639cb7c5f41461028d57600080fd5b80631cdf6343116100ee5780631cdf6343146101af57806336b402fb146101c2578063398f37731461020a57806350c946fe1461021d57600080fd5b80630c5801e314610120578063117392ce146101355780631257001114610148578063181f5a7714610170575b600080fd5b61013361012e366004611b8d565b61030e565b005b610133610143366004611bf9565b61061f565b61015b610156366004611c11565b61086a565b60405190151581526020015b60405180910390f35b604080518082018252601881527f4361706162696c697479526567697374727920312e302e300000000000000000602082015290516101679190611c8e565b6101336101bd366004611ca1565b61087d565b6101fc6101d0366004611ce3565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b604051908152602001610167565b610133610218366004611ca1565b610940565b61023061022b366004611c11565b610ad9565b6040516101679190611d05565b61025061024b366004611c11565b610ba1565b6040516101679190611d8b565b610133610c7e565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610167565b6102a061029b366004611c11565b610d7b565b6040516101679190611e6d565b6101336102bb366004611c11565b610e25565b6101336102ce366004611ca1565b610ef0565b6101336102e1366004611ca1565b61130c565b6102ee6116ed565b6040516101679190611e7b565b610133610309366004611eeb565b611832565b828114610356576040517fab8b67c600000000000000000000000000000000000000000000000000000000815260048101849052602481018290526044015b60405180910390fd5b6000805473ffffffffffffffffffffffffffffffffffffffff16905b8481101561061757600086868381811061038e5761038e611f08565b90506020020135905060008585848181106103ab576103ab611f08565b90506020028101906103bd9190611f37565b6103c69061203f565b805190915073ffffffffffffffffffffffffffffffffffffffff16610417576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16331480159061045457503373ffffffffffffffffffffffffffffffffffffffff851614155b1561048b576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160008381526007602052604090205473ffffffffffffffffffffffffffffffffffffffff908116911614158061053d57506020808201516040516104d19201611c8e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600086815260078352929092209192610524926001019101612158565b6040516020818303038152906040528051906020012014155b15610604578051600083815260076020908152604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921782558201516001909101906105aa9082612247565b50806000015173ffffffffffffffffffffffffffffffffffffffff167f14c8f513e8a6d86d2d16b0cb64976de4e72386c4f8068eca3b7354373f8fe97a8383602001516040516105fb929190612361565b60405180910390a25b505080610610906123a9565b9050610372565b505050505050565b610627611846565b60408051823560208281019190915280840135828401528251808303840181526060909201909252805191012061065f6003826118c9565b15610696576040517fe288638f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006106a86080840160608501611eeb565b73ffffffffffffffffffffffffffffffffffffffff1614610813576106d36080830160608401611eeb565b73ffffffffffffffffffffffffffffffffffffffff163b15806107b357506107016080830160608401611eeb565b6040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f884efe6100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff91909116906301ffc9a790602401602060405180830381865afa15801561078d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b191906123e1565b155b15610813576107c86080830160608401611eeb565b6040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161034d565b61081e6003826118e4565b50600081815260026020526040902082906108398282612403565b505060405181907f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff0690600090a25050565b60006108776005836118c9565b92915050565b610885611846565b60005b8181101561093b5760008383838181106108a4576108a4611f08565b60209081029290920135600081815260079093526040832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559093509190506108f56001830182611aa7565b50506040518181527f1e5877d7b3001d1569bf733b76c7eceda58bd6c031e5b8d0b7042308ba2e9d4f9060200160405180910390a150610934816123a9565b9050610888565b505050565b610948611846565b60005b8181101561093b57600083838381811061096757610967611f08565b90506020028101906109799190611f37565b6109829061203f565b805190915073ffffffffffffffffffffffffffffffffffffffff166109d3576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600954604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526007909252939020825181547fffffffffffffffffffffffff000000000000000000000000000000000000000016921691909117815591519091906001820190610a569082612247565b50905050600960008154610a69906123a9565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b91610abe91859190612361565b60405180910390a2505080610ad2906123a9565b905061094b565b6040805160808101825260008082526020820181905291810191909152606080820152600082815260086020908152604091829020825160808101845281548152600182015481840152600282015473ffffffffffffffffffffffffffffffffffffffff16818501526003820180548551818602810186019096528086529194929360608601939290830182828015610b9157602002820191906000526020600020905b815481526020019060010190808311610b7d575b5050505050815250509050919050565b6040805180820190915260008152606060208201526000828152600760209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610bfe9061210b565b80601f0160208091040260200160405190810160405280929190818152602001828054610c2a9061210b565b8015610b915780601f10610c4c57610100808354040283529160200191610b91565b820191906000526020600020905b815481529060010190602001808311610c5a57505050919092525091949350505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610cff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161034d565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b604080516080808201835260008083526020808401829052838501829052606084018290528582526002808252918590208551938401865280548452600180820154928501929092529182015493949293919284019160ff1690811115610de457610de4611dce565b6001811115610df557610df5611dce565b815260029190910154610100900473ffffffffffffffffffffffffffffffffffffffff1660209091015292915050565b610e2d611846565b610e386003826118c9565b610e71576040517fe181733f0000000000000000000000000000000000000000000000000000000081526004810182905260240161034d565b610e7c6005826118c9565b15610eb6576040517f16950d1d0000000000000000000000000000000000000000000000000000000081526004810182905260240161034d565b610ec16005826118e4565b5060405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf2190600090a250565b60005b8181101561093b576000838383818110610f0f57610f0f611f08565b9050602002810190610f219190612485565b610f2a906124b9565b90506000610f4d60005473ffffffffffffffffffffffffffffffffffffffff1690565b825160009081526007602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff90811683526001820180549690911633149650939491939092840191610fa49061210b565b80601f0160208091040260200160405190810160405280929190818152602001828054610fd09061210b565b801561101d5780601f10610ff25761010080835404028352916020019161101d565b820191906000526020600020905b81548152906001019060200180831161100057829003601f168201915b50505050508152505090508115801561104d5750805173ffffffffffffffffffffffffffffffffffffffff163314155b15611084576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020808401516000908152600890915260409020600301541515806110dd5783602001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161034d91815260200190565b604084015173ffffffffffffffffffffffffffffffffffffffff1661112e576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360600151516000036111735783606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161034d919061258e565b60005b846060015151811015611200576111b48560600151828151811061119c5761119c611f08565b602002602001015160036118c990919063ffffffff16565b6111f05784606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161034d919061258e565b6111f9816123a9565b9050611176565b506020848101805160009081526008835260409081902087518155915160018301558601516002820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055606086015180518793611285926003850192910190611ae1565b509050507f6bbba867c646be512c2f3241e65fdffdefd5528d7e7939649e06e10ee5addc3e8460200151856000015186604001516040516112ef93929190928352602083019190915273ffffffffffffffffffffffffffffffffffffffff16604082015260600190565b60405180910390a15050505080611305906123a9565b9050610ef3565b60005b8181101561093b57600083838381811061132b5761132b611f08565b905060200281019061133d9190612485565b611346906124b9565b9050600061136960005473ffffffffffffffffffffffffffffffffffffffff1690565b825160009081526007602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff908116835260018201805496909116331496509394919390928401916113c09061210b565b80601f01602080910402602001604051908101604052809291908181526020018280546113ec9061210b565b80156114395780601f1061140e57610100808354040283529160200191611439565b820191906000526020600020905b81548152906001019060200180831161141c57829003601f168201915b5050505050815250509050811580156114695750805173ffffffffffffffffffffffffffffffffffffffff163314155b156114a0576040517fef67f5d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602080840151600090815260089091526040902060030154151580806114c857506020840151155b156115075783602001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161034d91815260200190565b604084015173ffffffffffffffffffffffffffffffffffffffff16611558576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83606001515160000361159d5783606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161034d919061258e565b60005b846060015151811015611612576115c68560600151828151811061119c5761119c611f08565b6116025784606001516040517f3748d4c600000000000000000000000000000000000000000000000000000000815260040161034d919061258e565b61160b816123a9565b90506115a0565b506020848101805160009081526008835260409081902087518155915160018301558601516002820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055606086015180518793611697926003850192910190611ae1565b505050602084810151855160408051928352928201527f5bfe8a52ad26ac6ee7b0cd46d2fd92be04735a31c45ef8aa3d4b7ea1b61bbc1f910160405180910390a150505050806116e6906123a9565b905061130f565b606060006116fb60036118f0565b9050600061170960056118fd565b825161171591906125c6565b67ffffffffffffffff81111561172d5761172d611f75565b60405190808252806020026020018201604052801561179d57816020015b6040805160808101825260008082526020808301829052928201819052606082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161174b5790505b5090506000805b83518110156118295760008482815181106117c1576117c1611f08565b602002602001015190506117df8160056118c990919063ffffffff16565b611818576117ec81610d7b565b8484815181106117fe576117fe611f08565b60200260200101819052508280611814906123a9565b9350505b50611822816123a9565b90506117a4565b50909392505050565b61183a611846565b61184381611907565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146118c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161034d565b565b600081815260018301602052604081205415155b9392505050565b60006118dd83836119fc565b606060006118dd83611a4b565b6000610877825490565b3373ffffffffffffffffffffffffffffffffffffffff821603611986576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161034d565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000818152600183016020526040812054611a4357508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610877565b506000610877565b606081600001805480602002602001604051908101604052809291908181526020018280548015611a9b57602002820191906000526020600020905b815481526020019060010190808311611a87575b50505050509050919050565b508054611ab39061210b565b6000825580601f10611ac3575050565b601f0160209004906000526020600020908101906118439190611b2c565b828054828255906000526020600020908101928215611b1c579160200282015b82811115611b1c578251825591602001919060010190611b01565b50611b28929150611b2c565b5090565b5b80821115611b285760008155600101611b2d565b60008083601f840112611b5357600080fd5b50813567ffffffffffffffff811115611b6b57600080fd5b6020830191508360208260051b8501011115611b8657600080fd5b9250929050565b60008060008060408587031215611ba357600080fd5b843567ffffffffffffffff80821115611bbb57600080fd5b611bc788838901611b41565b90965094506020870135915080821115611be057600080fd5b50611bed87828801611b41565b95989497509550505050565b600060808284031215611c0b57600080fd5b50919050565b600060208284031215611c2357600080fd5b5035919050565b6000815180845260005b81811015611c5057602081850181015186830182015201611c34565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006118dd6020830184611c2a565b60008060208385031215611cb457600080fd5b823567ffffffffffffffff811115611ccb57600080fd5b611cd785828601611b41565b90969095509350505050565b60008060408385031215611cf657600080fd5b50508035926020909101359150565b6000602080835260a0830184518285015281850151604085015273ffffffffffffffffffffffffffffffffffffffff6040860151166060850152606085015160808086015281815180845260c0870191508483019350600092505b80831015611d805783518252928401926001929092019190840190611d60565b509695505050505050565b6020815273ffffffffffffffffffffffffffffffffffffffff825116602082015260006020830151604080840152611dc66060840182611c2a565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8051825260208101516020830152604081015160028110611e47577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b604083015260609081015173ffffffffffffffffffffffffffffffffffffffff16910152565b608081016108778284611dfd565b6020808252825182820181905260009190848201906040850190845b81811015611ebd57611eaa838551611dfd565b9284019260809290920191600101611e97565b50909695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461184357600080fd5b600060208284031215611efd57600080fd5b81356118dd81611ec9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112611f6b57600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611fc757611fc7611f75565b60405290565b6040516080810167ffffffffffffffff81118282101715611fc757611fc7611f75565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561203757612037611f75565b604052919050565b60006040823603121561205157600080fd5b612059611fa4565b823561206481611ec9565b815260208381013567ffffffffffffffff8082111561208257600080fd5b9085019036601f83011261209557600080fd5b8135818111156120a7576120a7611f75565b6120d7847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611ff0565b915080825236848285010111156120ed57600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c9082168061211f57607f821691505b602082108103611c0b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060208083526000845461216c8161210b565b8084870152604060018084166000811461218d57600181146121c5576121f3565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a010195506121f3565b896000528660002060005b858110156121eb5781548b82018601529083019088016121d0565b8a0184019650505b509398975050505050505050565b601f82111561093b57600081815260208120601f850160051c810160208610156122285750805b601f850160051c820191505b8181101561061757828155600101612234565b815167ffffffffffffffff81111561226157612261611f75565b6122758161226f845461210b565b84612201565b602080601f8311600181146122c857600084156122925750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610617565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015612315578886015182559484019460019091019084016122f6565b508582101561235157878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b828152604060208201526000611dc66040830184611c2a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036123da576123da61237a565b5060010190565b6000602082840312156123f357600080fd5b815180151581146118dd57600080fd5b81358155602082013560018201556002810160408301356002811061242757600080fd5b8154606085013561243781611ec9565b74ffffffffffffffffffffffffffffffffffffffff008160081b1660ff84167fffffffffffffffffffffff000000000000000000000000000000000000000000841617178455505050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112611f6b57600080fd5b6000608082360312156124cb57600080fd5b6124d3611fcd565b823581526020808401358183015260408401356124ef81611ec9565b6040830152606084013567ffffffffffffffff8082111561250f57600080fd5b9085019036601f83011261252257600080fd5b81358181111561253457612534611f75565b8060051b9150612545848301611ff0565b818152918301840191848101903684111561255f57600080fd5b938501935b8385101561257d57843582529385019390850190612564565b606087015250939695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015611ebd578351835292840192918401916001016125aa565b818103818111156108775761087761237a56fea164736f6c6343000813000a", } var CapabilityRegistryABI = CapabilityRegistryMetaData.ABI @@ -462,6 +462,18 @@ func (_CapabilityRegistry *CapabilityRegistryTransactorSession) UpdateNodeOperat return _CapabilityRegistry.Contract.UpdateNodeOperators(&_CapabilityRegistry.TransactOpts, nodeOperatorIds, nodeOperators) } +func (_CapabilityRegistry *CapabilityRegistryTransactor) UpdateNodes(opts *bind.TransactOpts, nodes []CapabilityRegistryNode) (*types.Transaction, error) { + return _CapabilityRegistry.contract.Transact(opts, "updateNodes", nodes) +} + +func (_CapabilityRegistry *CapabilityRegistrySession) UpdateNodes(nodes []CapabilityRegistryNode) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.UpdateNodes(&_CapabilityRegistry.TransactOpts, nodes) +} + +func (_CapabilityRegistry *CapabilityRegistryTransactorSession) UpdateNodes(nodes []CapabilityRegistryNode) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.UpdateNodes(&_CapabilityRegistry.TransactOpts, nodes) +} + type CapabilityRegistryCapabilityAddedIterator struct { Event *CapabilityRegistryCapabilityAdded @@ -1209,6 +1221,125 @@ func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseNodeOperatorUpdated( return event, nil } +type CapabilityRegistryNodeUpdatedIterator struct { + Event *CapabilityRegistryNodeUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilityRegistryNodeUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryNodeUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryNodeUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CapabilityRegistryNodeUpdatedIterator) Error() error { + return it.fail +} + +func (it *CapabilityRegistryNodeUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilityRegistryNodeUpdated struct { + P2pId [32]byte + NodeOperatorId *big.Int + Signer common.Address + Raw types.Log +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterNodeUpdated(opts *bind.FilterOpts) (*CapabilityRegistryNodeUpdatedIterator, error) { + + logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "NodeUpdated") + if err != nil { + return nil, err + } + return &CapabilityRegistryNodeUpdatedIterator{contract: _CapabilityRegistry.contract, event: "NodeUpdated", logs: logs, sub: sub}, nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchNodeUpdated(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeUpdated) (event.Subscription, error) { + + logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "NodeUpdated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilityRegistryNodeUpdated) + if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseNodeUpdated(log types.Log) (*CapabilityRegistryNodeUpdated, error) { + event := new(CapabilityRegistryNodeUpdated) + if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type CapabilityRegistryOwnershipTransferRequestedIterator struct { Event *CapabilityRegistryOwnershipTransferRequested @@ -1495,6 +1626,8 @@ func (_CapabilityRegistry *CapabilityRegistry) ParseLog(log types.Log) (generate return _CapabilityRegistry.ParseNodeOperatorRemoved(log) case _CapabilityRegistry.abi.Events["NodeOperatorUpdated"].ID: return _CapabilityRegistry.ParseNodeOperatorUpdated(log) + case _CapabilityRegistry.abi.Events["NodeUpdated"].ID: + return _CapabilityRegistry.ParseNodeUpdated(log) case _CapabilityRegistry.abi.Events["OwnershipTransferRequested"].ID: return _CapabilityRegistry.ParseOwnershipTransferRequested(log) case _CapabilityRegistry.abi.Events["OwnershipTransferred"].ID: @@ -1529,6 +1662,10 @@ func (CapabilityRegistryNodeOperatorUpdated) Topic() common.Hash { return common.HexToHash("0x14c8f513e8a6d86d2d16b0cb64976de4e72386c4f8068eca3b7354373f8fe97a") } +func (CapabilityRegistryNodeUpdated) Topic() common.Hash { + return common.HexToHash("0x6bbba867c646be512c2f3241e65fdffdefd5528d7e7939649e06e10ee5addc3e") +} + func (CapabilityRegistryOwnershipTransferRequested) Topic() common.Hash { return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") } @@ -1574,6 +1711,8 @@ type CapabilityRegistryInterface interface { UpdateNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []*big.Int, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) + UpdateNodes(opts *bind.TransactOpts, nodes []CapabilityRegistryNode) (*types.Transaction, error) + FilterCapabilityAdded(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilityRegistryCapabilityAddedIterator, error) WatchCapabilityAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityAdded, hashedCapabilityId [][32]byte) (event.Subscription, error) @@ -1610,6 +1749,12 @@ type CapabilityRegistryInterface interface { ParseNodeOperatorUpdated(log types.Log) (*CapabilityRegistryNodeOperatorUpdated, error) + FilterNodeUpdated(opts *bind.FilterOpts) (*CapabilityRegistryNodeUpdatedIterator, error) + + WatchNodeUpdated(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeUpdated) (event.Subscription, error) + + ParseNodeUpdated(log types.Log) (*CapabilityRegistryNodeUpdated, error) + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilityRegistryOwnershipTransferRequestedIterator, error) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) diff --git a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 182c8da3f7e..e2bb9865809 100644 --- a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,4 +1,4 @@ GETH_VERSION: 1.13.8 forwarder: ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.bin b4c900aae9e022f01abbac7993d41f93912247613ac6270b0c4da4ef6f2016e3 -keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin aeb366351d69f320c610419a3e09a991bd6ea75690778835eb8f6421d1277f44 +keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin 98d53a1997053a3037827ffd170c12f49d2005a5c266a1ea9eb69bb51e862f37 ocr3_capability: ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.bin 9dcbdf55bd5729ba266148da3f17733eb592c871c2108ccca546618628fd9ad2 From 09f8c7fcd63bd4cc11a193b49f808f42e3d1f37a Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Mon, 6 May 2024 18:40:29 +0200 Subject: [PATCH 43/45] [TT-849] Move TestConfig's common parts to CTF (#13046) * use latest Seth * move test config to CTF * use latest CTF that fixes eth2 genesis generation * use latest Seth * use tagged CTF version --- integration-tests/actions/private_network.go | 8 ++--- .../actions/vrf/vrfv2/setup_steps.go | 2 +- .../actions/vrf/vrfv2plus/setup_steps.go | 2 +- .../docker/cmd/internal/commands.go | 2 +- integration-tests/docker/test_env/test_env.go | 31 ++++++++++--------- .../docker/test_env/test_env_builder.go | 14 ++++----- .../docker/test_env/test_env_config.go | 12 +++---- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 +-- .../load/functions/onchain_monitoring.go | 4 +-- integration-tests/load/functions/setup.go | 4 +-- integration-tests/load/go.mod | 4 +-- integration-tests/load/go.sum | 8 ++--- .../migration/upgrade_version_test.go | 2 +- integration-tests/smoke/automation_test.go | 4 +-- integration-tests/smoke/cron_test.go | 4 +-- integration-tests/smoke/flux_test.go | 2 +- integration-tests/smoke/forwarder_ocr_test.go | 2 +- .../smoke/forwarders_ocr2_test.go | 2 +- integration-tests/smoke/keeper_test.go | 2 +- integration-tests/smoke/ocr2_test.go | 2 +- integration-tests/smoke/ocr_test.go | 2 +- integration-tests/smoke/runlog_test.go | 2 +- integration-tests/smoke/vrf_test.go | 2 +- integration-tests/testconfig/testconfig.go | 31 ++----------------- .../testconfig/testconfig_test.go | 16 +++++----- integration-tests/types/testconfigs.go | 19 ++++++------ .../universal/log_poller/helpers.go | 2 +- 28 files changed, 84 insertions(+), 107 deletions(-) diff --git a/integration-tests/actions/private_network.go b/integration-tests/actions/private_network.go index 01a084b66d8..70239a60060 100644 --- a/integration-tests/actions/private_network.go +++ b/integration-tests/actions/private_network.go @@ -3,17 +3,17 @@ package actions import ( "github.com/rs/zerolog" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) -func EthereumNetworkConfigFromConfig(l zerolog.Logger, config tc.GlobalTestConfig) (network ctf_test_env.EthereumNetwork, err error) { +func EthereumNetworkConfigFromConfig(l zerolog.Logger, config ctf_config.GlobalTestConfig) (network ctf_test_env.EthereumNetwork, err error) { if config.GetPrivateEthereumNetworkConfig() == nil { l.Warn().Msg("No TOML private ethereum network config found, will use old geth") ethBuilder := ctf_test_env.NewEthereumNetworkBuilder() network, err = ethBuilder. - WithEthereumVersion(ctf_test_env.EthereumVersion_Eth1). - WithExecutionLayer(ctf_test_env.ExecutionLayer_Geth). + WithEthereumVersion(ctf_config.EthereumVersion_Eth1). + WithExecutionLayer(ctf_config.ExecutionLayer_Geth). Build() return diff --git a/integration-tests/actions/vrf/vrfv2/setup_steps.go b/integration-tests/actions/vrf/vrfv2/setup_steps.go index bd41fb33e4e..ca85bdb5f19 100644 --- a/integration-tests/actions/vrf/vrfv2/setup_steps.go +++ b/integration-tests/actions/vrf/vrfv2/setup_steps.go @@ -359,7 +359,7 @@ func SetupVRFV2ForNewEnv( env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&testConfig). - WithPrivateEthereumNetwork(network). + WithPrivateEthereumNetwork(network.EthereumNetworkConfig). WithCLNodes(len(newEnvConfig.NodesToCreate)). WithFunding(big.NewFloat(*testConfig.Common.ChainlinkNodeFunding)). WithCustomCleanup(cleanupFn). diff --git a/integration-tests/actions/vrf/vrfv2plus/setup_steps.go b/integration-tests/actions/vrf/vrfv2plus/setup_steps.go index 0b7be600cc2..ed81935fa2b 100644 --- a/integration-tests/actions/vrf/vrfv2plus/setup_steps.go +++ b/integration-tests/actions/vrf/vrfv2plus/setup_steps.go @@ -402,7 +402,7 @@ func SetupVRFV2PlusForNewEnv( env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&testConfig). - WithPrivateEthereumNetwork(network). + WithPrivateEthereumNetwork(network.EthereumNetworkConfig). WithCLNodes(len(newEnvConfig.NodesToCreate)). WithFunding(big.NewFloat(*testConfig.Common.ChainlinkNodeFunding)). WithCustomCleanup(cleanupFn). diff --git a/integration-tests/docker/cmd/internal/commands.go b/integration-tests/docker/cmd/internal/commands.go index 074cfb8083d..e05e5d89fac 100644 --- a/integration-tests/docker/cmd/internal/commands.go +++ b/integration-tests/docker/cmd/internal/commands.go @@ -43,7 +43,7 @@ var StartNodesCmd = &cobra.Command{ _, err = test_env.NewCLTestEnvBuilder(). WithTestConfig(&config). - WithPrivateEthereumNetwork(network). + WithPrivateEthereumNetwork(network.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(nodeCount). WithoutCleanup(). diff --git a/integration-tests/docker/test_env/test_env.go b/integration-tests/docker/test_env/test_env.go index fc0ba355556..fd1555ec055 100644 --- a/integration-tests/docker/test_env/test_env.go +++ b/integration-tests/docker/test_env/test_env.go @@ -18,6 +18,7 @@ import ( tc "github.com/testcontainers/testcontainers-go" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" "github.com/smartcontractkit/chainlink-testing-framework/docker" "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" "github.com/smartcontractkit/chainlink-testing-framework/logging" @@ -29,7 +30,6 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" d "github.com/smartcontractkit/chainlink/integration-tests/docker" - core_testconfig "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) var ( @@ -40,7 +40,7 @@ type CLClusterTestEnv struct { Cfg *TestEnvConfig DockerNetwork *tc.DockerNetwork LogStream *logstream.LogStream - TestConfig core_testconfig.GlobalTestConfig + TestConfig ctf_config.GlobalTestConfig /* components */ ClCluster *ClCluster @@ -49,7 +49,7 @@ type CLClusterTestEnv struct { sethClients map[int64]*seth.Client ContractDeployer contracts.ContractDeployer ContractLoader contracts.ContractLoader - PrivateEthereumConfigs []*test_env.EthereumNetwork // new approach to private chains, supporting eth1 and eth2 + PrivateEthereumConfigs []*ctf_config.EthereumNetworkConfig EVMNetworks []*blockchain.EVMNetwork rpcProviders map[int64]*test_env.RpcProvider l zerolog.Logger @@ -95,18 +95,11 @@ func (te *CLClusterTestEnv) ParallelTransactions(enabled bool) { } } -func (te *CLClusterTestEnv) StartEthereumNetwork(cfg *test_env.EthereumNetwork) (blockchain.EVMNetwork, test_env.RpcProvider, error) { +func (te *CLClusterTestEnv) StartEthereumNetwork(cfg *ctf_config.EthereumNetworkConfig) (blockchain.EVMNetwork, test_env.RpcProvider, error) { // if environment is being restored from a previous state, use the existing config // this might fail terribly if temporary folders with chain data on the host machine were removed - if te.Cfg != nil && te.Cfg.EthereumNetwork != nil { - builder := test_env.NewEthereumNetworkBuilder() - c, err := builder.WithExistingConfig(*te.Cfg.EthereumNetwork). - WithTest(te.t). - Build() - if err != nil { - return blockchain.EVMNetwork{}, test_env.RpcProvider{}, err - } - cfg = &c + if te.Cfg != nil && te.Cfg.EthereumNetworkConfig != nil { + cfg = te.Cfg.EthereumNetworkConfig } te.l.Info(). @@ -115,7 +108,15 @@ func (te *CLClusterTestEnv) StartEthereumNetwork(cfg *test_env.EthereumNetwork) Str("Custom Docker Images", fmt.Sprintf("%v", cfg.CustomDockerImages)). Msg("Starting Ethereum network") - n, rpc, err := cfg.Start() + builder := test_env.NewEthereumNetworkBuilder() + c, err := builder.WithExistingConfig(*cfg). + WithTest(te.t). + Build() + if err != nil { + return blockchain.EVMNetwork{}, test_env.RpcProvider{}, err + } + + n, rpc, err := c.Start() if err != nil { return blockchain.EVMNetwork{}, test_env.RpcProvider{}, err @@ -129,7 +130,7 @@ func (te *CLClusterTestEnv) StartMockAdapter() error { } // pass config here -func (te *CLClusterTestEnv) StartClCluster(nodeConfig *chainlink.Config, count int, secretsConfig string, testconfig core_testconfig.GlobalTestConfig, opts ...ClNodeOption) error { +func (te *CLClusterTestEnv) StartClCluster(nodeConfig *chainlink.Config, count int, secretsConfig string, testconfig ctf_config.GlobalTestConfig, opts ...ClNodeOption) error { if te.Cfg != nil && te.Cfg.ClCluster != nil { te.ClCluster = te.Cfg.ClCluster } else { diff --git a/integration-tests/docker/test_env/test_env_builder.go b/integration-tests/docker/test_env/test_env_builder.go index c2aa07c8fa9..c8b4ac8e734 100644 --- a/integration-tests/docker/test_env/test_env_builder.go +++ b/integration-tests/docker/test_env/test_env_builder.go @@ -12,6 +12,7 @@ import ( "github.com/smartcontractkit/seth" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/logstream" @@ -23,7 +24,6 @@ import ( actions_seth "github.com/smartcontractkit/chainlink/integration-tests/actions/seth" "github.com/smartcontractkit/chainlink/integration-tests/contracts" - tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" "github.com/smartcontractkit/chainlink/integration-tests/utils" ) @@ -56,8 +56,8 @@ type CLTestEnvBuilder struct { cleanUpCustomFn func() chainOptionsFn []ChainOption evmClientNetworkOption []EVMClientNetworkOption - privateEthereumNetworks []*test_env.EthereumNetwork - testConfig tc.GlobalTestConfig + privateEthereumNetworks []*ctf_config.EthereumNetworkConfig + testConfig ctf_config.GlobalTestConfig /* funding */ ETHFunds *big.Float @@ -120,7 +120,7 @@ func (b *CLTestEnvBuilder) WithCLNodes(clNodesCount int) *CLTestEnvBuilder { return b } -func (b *CLTestEnvBuilder) WithTestConfig(cfg tc.GlobalTestConfig) *CLTestEnvBuilder { +func (b *CLTestEnvBuilder) WithTestConfig(cfg ctf_config.GlobalTestConfig) *CLTestEnvBuilder { b.testConfig = cfg return b } @@ -146,12 +146,12 @@ func (b *CLTestEnvBuilder) WithSeth() *CLTestEnvBuilder { return b } -func (b *CLTestEnvBuilder) WithPrivateEthereumNetwork(en test_env.EthereumNetwork) *CLTestEnvBuilder { +func (b *CLTestEnvBuilder) WithPrivateEthereumNetwork(en ctf_config.EthereumNetworkConfig) *CLTestEnvBuilder { b.privateEthereumNetworks = append(b.privateEthereumNetworks, &en) return b } -func (b *CLTestEnvBuilder) WithPrivateEthereumNetworks(ens []*test_env.EthereumNetwork) *CLTestEnvBuilder { +func (b *CLTestEnvBuilder) WithPrivateEthereumNetworks(ens []*ctf_config.EthereumNetworkConfig) *CLTestEnvBuilder { b.privateEthereumNetworks = ens return b } @@ -300,7 +300,7 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { if err != nil { return nil, err } - b.privateEthereumNetworks[i] = &netWithLs + b.privateEthereumNetworks[i] = &netWithLs.EthereumNetworkConfig } } diff --git a/integration-tests/docker/test_env/test_env_config.go b/integration-tests/docker/test_env/test_env_config.go index 0902deb0c2d..9aefa9615c9 100644 --- a/integration-tests/docker/test_env/test_env_config.go +++ b/integration-tests/docker/test_env/test_env_config.go @@ -3,16 +3,16 @@ package test_env import ( "encoding/json" - cte "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" env "github.com/smartcontractkit/chainlink/integration-tests/types/envcommon" ) type TestEnvConfig struct { - Networks []string `json:"networks"` - Geth GethConfig `json:"geth"` - MockAdapter MockAdapterConfig `json:"mock_adapter"` - ClCluster *ClCluster `json:"clCluster"` - EthereumNetwork *cte.EthereumNetwork `json:"private_ethereum_config"` + Networks []string `json:"networks"` + Geth GethConfig `json:"geth"` + MockAdapter MockAdapterConfig `json:"mock_adapter"` + ClCluster *ClCluster `json:"clCluster"` + EthereumNetworkConfig *ctf_config.EthereumNetworkConfig `json:"private_ethereum_config"` } type MockAdapterConfig struct { diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 3d76a656be5..babf82a7d96 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -26,7 +26,7 @@ require ( github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.3 github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb - github.com/smartcontractkit/chainlink-testing-framework v1.28.7 + github.com/smartcontractkit/chainlink-testing-framework v1.28.8 github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 61fef05bbad..95f686a6d28 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1529,8 +1529,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba5 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba58/go.mod h1:oV5gIuSKrPEcjQ6uB6smBsm5kXHxyydVLNyAs4V9CoQ= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595 h1:y6ks0HsSOhPUueOmTcoxDQ50RCS1XINlRDTemZyHjFw= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595/go.mod h1:vV6WfnVIbK5Q1JsIru4YcTG0T1uRpLJm6t2BgCnCSsg= -github.com/smartcontractkit/chainlink-testing-framework v1.28.7 h1:Yr93tBl5jVx1cfKywt0C0cbuObDPJ6JIU4FIsZ6bZlM= -github.com/smartcontractkit/chainlink-testing-framework v1.28.7/go.mod h1:x1zDOz8zcLjEvs9fNA9y/DMguLam/2+CJdpxX0+rM8A= +github.com/smartcontractkit/chainlink-testing-framework v1.28.8 h1:EaxNwB/16wpISzaUn2WJ4bE3TawD3joEekIlQuWNRGo= +github.com/smartcontractkit/chainlink-testing-framework v1.28.8/go.mod h1:x1zDOz8zcLjEvs9fNA9y/DMguLam/2+CJdpxX0+rM8A= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= diff --git a/integration-tests/load/functions/onchain_monitoring.go b/integration-tests/load/functions/onchain_monitoring.go index 12a10ce0042..31ca8752dd3 100644 --- a/integration-tests/load/functions/onchain_monitoring.go +++ b/integration-tests/load/functions/onchain_monitoring.go @@ -7,7 +7,7 @@ import ( "github.com/rs/zerolog/log" "github.com/smartcontractkit/wasp" - tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" ) /* Monitors on-chain stats of LoadConsumer and pushes them to Loki every second */ @@ -25,7 +25,7 @@ type LoadStats struct { Empty uint32 } -func MonitorLoadStats(t *testing.T, ft *FunctionsTest, labels map[string]string, config tc.GlobalTestConfig) { +func MonitorLoadStats(t *testing.T, ft *FunctionsTest, labels map[string]string, config ctf_config.GlobalTestConfig) { go func() { updatedLabels := make(map[string]string) for k, v := range labels { diff --git a/integration-tests/load/functions/setup.go b/integration-tests/load/functions/setup.go index 4e353ff93a9..190dbbd8692 100644 --- a/integration-tests/load/functions/setup.go +++ b/integration-tests/load/functions/setup.go @@ -16,8 +16,8 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/networks" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" "github.com/smartcontractkit/chainlink/integration-tests/contracts" - tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" "github.com/smartcontractkit/chainlink/integration-tests/types" "github.com/smartcontractkit/chainlink/integration-tests/utils" chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" @@ -50,7 +50,7 @@ type S4SecretsCfg struct { S4SetPayload string } -func SetupLocalLoadTestEnv(globalConfig tc.GlobalTestConfig, functionsConfig types.FunctionsTestConfig) (*FunctionsTest, error) { +func SetupLocalLoadTestEnv(globalConfig ctf_config.GlobalTestConfig, functionsConfig types.FunctionsTestConfig) (*FunctionsTest, error) { selectedNetwork := networks.MustGetSelectedNetworkConfig(globalConfig.GetNetworkConfig())[0] readSethCfg := globalConfig.GetSethConfig() sethCfg, err := utils.MergeSethAndEvmNetworkConfigs(selectedNetwork, *readSethCfg) diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index c8fde175cab..c179a3619f7 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -17,11 +17,11 @@ require ( github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.3 github.com/smartcontractkit/chainlink-common v0.1.7-0.20240429120925-907b29311feb - github.com/smartcontractkit/chainlink-testing-framework v1.28.7 + github.com/smartcontractkit/chainlink-testing-framework v1.28.8 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c - github.com/smartcontractkit/seth v0.1.6 + github.com/smartcontractkit/seth v0.1.6-0.20240429143720-cacb8160ecec github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 github.com/smartcontractkit/wasp v0.4.6 github.com/stretchr/testify v1.9.0 diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 46646e6b289..2c31f0fa335 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1512,8 +1512,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba5 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240422172640-59d47c73ba58/go.mod h1:oV5gIuSKrPEcjQ6uB6smBsm5kXHxyydVLNyAs4V9CoQ= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595 h1:y6ks0HsSOhPUueOmTcoxDQ50RCS1XINlRDTemZyHjFw= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595/go.mod h1:vV6WfnVIbK5Q1JsIru4YcTG0T1uRpLJm6t2BgCnCSsg= -github.com/smartcontractkit/chainlink-testing-framework v1.28.7 h1:Yr93tBl5jVx1cfKywt0C0cbuObDPJ6JIU4FIsZ6bZlM= -github.com/smartcontractkit/chainlink-testing-framework v1.28.7/go.mod h1:x1zDOz8zcLjEvs9fNA9y/DMguLam/2+CJdpxX0+rM8A= +github.com/smartcontractkit/chainlink-testing-framework v1.28.8 h1:EaxNwB/16wpISzaUn2WJ4bE3TawD3joEekIlQuWNRGo= +github.com/smartcontractkit/chainlink-testing-framework v1.28.8/go.mod h1:x1zDOz8zcLjEvs9fNA9y/DMguLam/2+CJdpxX0+rM8A= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240227164431-18a7065e23ea h1:ZdLmNAfKRjH8AYUvjiiDGUgiWQfq/7iNpxyTkvjx/ko= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240227164431-18a7065e23ea/go.mod h1:gCKC9w6XpNk6jm+XIk2psrkkfxhi421N9NSiFceXW88= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= @@ -1524,8 +1524,8 @@ github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJ github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c h1:lIyMbTaF2H0Q71vkwZHX/Ew4KF2BxiKhqEXwF8rn+KI= github.com/smartcontractkit/libocr v0.0.0-20240419185742-fd3cab206b2c/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= -github.com/smartcontractkit/seth v0.1.6 h1:exU96KiKM/gxvp7OR8KkOXnTgbtFNepdhMBvyobFKCw= -github.com/smartcontractkit/seth v0.1.6/go.mod h1:2TMOZQ8WTAw7rR1YBbXpnad6VmT/+xDd/nXLmB7Eero= +github.com/smartcontractkit/seth v0.1.6-0.20240429143720-cacb8160ecec h1:BT1loU6TT2YqMenD7XE+aw7IeeTiC25+r1TLKAySVIg= +github.com/smartcontractkit/seth v0.1.6-0.20240429143720-cacb8160ecec/go.mod h1:2TMOZQ8WTAw7rR1YBbXpnad6VmT/+xDd/nXLmB7Eero= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ= diff --git a/integration-tests/migration/upgrade_version_test.go b/integration-tests/migration/upgrade_version_test.go index 47761c09e50..f89644eb815 100644 --- a/integration-tests/migration/upgrade_version_test.go +++ b/integration-tests/migration/upgrade_version_test.go @@ -30,7 +30,7 @@ func TestVersionUpgrade(t *testing.T) { WithTestConfig(&config). WithTestInstance(t). WithStandardCleanup(). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithCLNodes(1). WithStandardCleanup(). WithSeth(). diff --git a/integration-tests/smoke/automation_test.go b/integration-tests/smoke/automation_test.go index 73a7749c4e1..81d18139122 100644 --- a/integration-tests/smoke/automation_test.go +++ b/integration-tests/smoke/automation_test.go @@ -1160,7 +1160,7 @@ func setupAutomationTestDocker( env, err = test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(automationTestConfig). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithFunding(big.NewFloat(*automationTestConfig.GetCommonConfig().ChainlinkNodeFunding)). WithStandardCleanup(). @@ -1200,7 +1200,7 @@ func setupAutomationTestDocker( env, err = test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(automationTestConfig). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(clNodesCount). WithCLNodeConfig(clNodeConfig). diff --git a/integration-tests/smoke/cron_test.go b/integration-tests/smoke/cron_test.go index 218727b7d66..e281824f0bb 100644 --- a/integration-tests/smoke/cron_test.go +++ b/integration-tests/smoke/cron_test.go @@ -32,7 +32,7 @@ func TestCronBasic(t *testing.T) { env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&config). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(1). WithStandardCleanup(). @@ -88,7 +88,7 @@ func TestCronJobReplacement(t *testing.T) { env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&config). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(1). WithStandardCleanup(). diff --git a/integration-tests/smoke/flux_test.go b/integration-tests/smoke/flux_test.go index 023dd9dae89..4165e9b79b7 100644 --- a/integration-tests/smoke/flux_test.go +++ b/integration-tests/smoke/flux_test.go @@ -39,7 +39,7 @@ func TestFluxBasic(t *testing.T) { env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&config). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(3). WithStandardCleanup(). diff --git a/integration-tests/smoke/forwarder_ocr_test.go b/integration-tests/smoke/forwarder_ocr_test.go index 5a8e51f871f..1ff132f09ab 100644 --- a/integration-tests/smoke/forwarder_ocr_test.go +++ b/integration-tests/smoke/forwarder_ocr_test.go @@ -35,7 +35,7 @@ func TestForwarderOCRBasic(t *testing.T) { env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&config). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithForwarders(). WithCLNodes(6). diff --git a/integration-tests/smoke/forwarders_ocr2_test.go b/integration-tests/smoke/forwarders_ocr2_test.go index ee86e8cc4b6..d3aa9e85ce6 100644 --- a/integration-tests/smoke/forwarders_ocr2_test.go +++ b/integration-tests/smoke/forwarders_ocr2_test.go @@ -38,7 +38,7 @@ func TestForwarderOCR2Basic(t *testing.T) { env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&config). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodeConfig(node.NewConfig(node.NewBaseConfig(), node.WithOCR2(), diff --git a/integration-tests/smoke/keeper_test.go b/integration-tests/smoke/keeper_test.go index 7f2183faeac..fbfe4c73c89 100644 --- a/integration-tests/smoke/keeper_test.go +++ b/integration-tests/smoke/keeper_test.go @@ -1166,7 +1166,7 @@ func setupKeeperTest(l zerolog.Logger, t *testing.T, config *tc.TestConfig) ( env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(config). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithCLNodes(5). WithCLNodeConfig(clNodeConfig). WithFunding(big.NewFloat(.5)). diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go index d4f7d1e7ffd..d2df0c858c0 100644 --- a/integration-tests/smoke/ocr2_test.go +++ b/integration-tests/smoke/ocr2_test.go @@ -138,7 +138,7 @@ func prepareORCv2SmokeTestEnv(t *testing.T, l zerolog.Logger, firstRoundResult i env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&config). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodeConfig(node.NewConfig(node.NewBaseConfig(), node.WithOCR2(), diff --git a/integration-tests/smoke/ocr_test.go b/integration-tests/smoke/ocr_test.go index 29e633beb15..bef08493962 100644 --- a/integration-tests/smoke/ocr_test.go +++ b/integration-tests/smoke/ocr_test.go @@ -91,7 +91,7 @@ func prepareORCv1SmokeTestEnv(t *testing.T, l zerolog.Logger, firstRoundResult i env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&config). - WithPrivateEthereumNetwork(network). + WithPrivateEthereumNetwork(network.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(6). WithFunding(big.NewFloat(.5)). diff --git a/integration-tests/smoke/runlog_test.go b/integration-tests/smoke/runlog_test.go index d255fe07235..b01c5a019b1 100644 --- a/integration-tests/smoke/runlog_test.go +++ b/integration-tests/smoke/runlog_test.go @@ -36,7 +36,7 @@ func TestRunLogBasic(t *testing.T) { env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&config). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithMockAdapter(). WithCLNodes(1). WithFunding(big.NewFloat(.1)). diff --git a/integration-tests/smoke/vrf_test.go b/integration-tests/smoke/vrf_test.go index 3a28c14be00..ed8f756396f 100644 --- a/integration-tests/smoke/vrf_test.go +++ b/integration-tests/smoke/vrf_test.go @@ -192,7 +192,7 @@ func prepareVRFtestEnv(t *testing.T, l zerolog.Logger) (*test_env.CLClusterTestE env, err := test_env.NewCLTestEnvBuilder(). WithTestInstance(t). WithTestConfig(&config). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithCLNodes(1). WithFunding(big.NewFloat(.1)). WithStandardCleanup(). diff --git a/integration-tests/testconfig/testconfig.go b/integration-tests/testconfig/testconfig.go index 30a795e1881..fbaf80a2c88 100644 --- a/integration-tests/testconfig/testconfig.go +++ b/integration-tests/testconfig/testconfig.go @@ -19,8 +19,6 @@ import ( "github.com/smartcontractkit/seth" ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" k8s_config "github.com/smartcontractkit/chainlink-testing-framework/k8s/config" "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/utils/osutil" @@ -35,15 +33,6 @@ import ( vrfv2plus_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/vrfv2plus" ) -type GlobalTestConfig interface { - GetChainlinkImageConfig() *ctf_config.ChainlinkImageConfig - GetLoggingConfig() *ctf_config.LoggingConfig - GetNetworkConfig() *ctf_config.NetworkConfig - GetPrivateEthereumNetworkConfig() *test_env.EthereumNetwork - GetPyroscopeConfig() *ctf_config.PyroscopeConfig - SethConfig -} - type UpgradeableChainlinkTestConfig interface { GetChainlinkUpgradeImageConfig() *ctf_config.ChainlinkImageConfig } @@ -80,24 +69,8 @@ type Ocr2TestConfig interface { GetOCR2Config() *ocr2_config.Config } -type NamedConfiguration interface { - GetConfigurationName() string -} - -type SethConfig interface { - GetSethConfig() *seth.Config -} - type TestConfig struct { - ChainlinkImage *ctf_config.ChainlinkImageConfig `toml:"ChainlinkImage"` - ChainlinkUpgradeImage *ctf_config.ChainlinkImageConfig `toml:"ChainlinkUpgradeImage"` - Logging *ctf_config.LoggingConfig `toml:"Logging"` - Network *ctf_config.NetworkConfig `toml:"Network"` - Pyroscope *ctf_config.PyroscopeConfig `toml:"Pyroscope"` - PrivateEthereumNetwork *ctf_test_env.EthereumNetwork `toml:"PrivateEthereumNetwork"` - WaspConfig *ctf_config.WaspAutoBuildConfig `toml:"WaspAutoBuild"` - - Seth *seth.Config `toml:"Seth"` + ctf_config.TestConfig Common *Common `toml:"Common"` Automation *a_config.Config `toml:"Automation"` @@ -182,7 +155,7 @@ func (c TestConfig) GetChainlinkImageConfig() *ctf_config.ChainlinkImageConfig { return c.ChainlinkImage } -func (c TestConfig) GetPrivateEthereumNetworkConfig() *ctf_test_env.EthereumNetwork { +func (c TestConfig) GetPrivateEthereumNetworkConfig() *ctf_config.EthereumNetworkConfig { return c.PrivateEthereumNetwork } diff --git a/integration-tests/testconfig/testconfig_test.go b/integration-tests/testconfig/testconfig_test.go index 4a9dbdaade3..fd5230dac2d 100644 --- a/integration-tests/testconfig/testconfig_test.go +++ b/integration-tests/testconfig/testconfig_test.go @@ -57,13 +57,15 @@ func TestBase64ConfigRead(t *testing.T) { }, }, }, - Network: &ctf_config.NetworkConfig{ - SelectedNetworks: []string{"OPTIMISM_GOERLI"}, - RpcHttpUrls: map[string][]string{ - "OPTIMISM_GOERLI": {"http://localhost:8545"}, - }, - WalletKeys: map[string][]string{ - "OPTIMISM_GOERLI": {"0x3333333333333333333333333333333333333333"}, + TestConfig: ctf_config.TestConfig{ + Network: &ctf_config.NetworkConfig{ + SelectedNetworks: []string{"OPTIMISM_GOERLI"}, + RpcHttpUrls: map[string][]string{ + "OPTIMISM_GOERLI": {"http://localhost:8545"}, + }, + WalletKeys: map[string][]string{ + "OPTIMISM_GOERLI": {"0x3333333333333333333333333333333333333333"}, + }, }, }, } diff --git a/integration-tests/types/testconfigs.go b/integration-tests/types/testconfigs.go index cfebf0a3c7a..58eb1a7c8cf 100644 --- a/integration-tests/types/testconfigs.go +++ b/integration-tests/types/testconfigs.go @@ -1,52 +1,53 @@ package types import ( + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" "github.com/smartcontractkit/chainlink-testing-framework/testreporters" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) type VRFv2TestConfig interface { tc.CommonTestConfig - tc.GlobalTestConfig + ctf_config.GlobalTestConfig tc.VRFv2TestConfig } type VRFv2PlusTestConfig interface { tc.CommonTestConfig - tc.GlobalTestConfig + ctf_config.GlobalTestConfig tc.VRFv2PlusTestConfig } type FunctionsTestConfig interface { tc.CommonTestConfig - tc.GlobalTestConfig + ctf_config.GlobalTestConfig tc.FunctionsTestConfig } type AutomationTestConfig interface { - tc.GlobalTestConfig + ctf_config.GlobalTestConfig tc.CommonTestConfig tc.UpgradeableChainlinkTestConfig tc.AutomationTestConfig } type KeeperBenchmarkTestConfig interface { - tc.GlobalTestConfig + ctf_config.GlobalTestConfig tc.CommonTestConfig tc.KeeperTestConfig - tc.NamedConfiguration + ctf_config.NamedConfiguration testreporters.GrafanaURLProvider } type OcrTestConfig interface { - tc.GlobalTestConfig + ctf_config.GlobalTestConfig tc.CommonTestConfig tc.OcrTestConfig - tc.SethConfig + ctf_config.SethConfig } type Ocr2TestConfig interface { - tc.GlobalTestConfig + ctf_config.GlobalTestConfig tc.CommonTestConfig tc.Ocr2TestConfig } diff --git a/integration-tests/universal/log_poller/helpers.go b/integration-tests/universal/log_poller/helpers.go index 4759818d11c..fe3732cb47b 100644 --- a/integration-tests/universal/log_poller/helpers.go +++ b/integration-tests/universal/log_poller/helpers.go @@ -1131,7 +1131,7 @@ func SetupLogPollerTestDocker( env, err = test_env.NewCLTestEnvBuilder(). WithTestConfig(testConfig). WithTestInstance(t). - WithPrivateEthereumNetwork(privateNetwork). + WithPrivateEthereumNetwork(privateNetwork.EthereumNetworkConfig). WithCLNodes(clNodesCount). WithCLNodeConfig(clNodeConfig). WithFunding(big.NewFloat(chainlinkNodeFunding)). From 0955d4657113e3e069429391783bd15bf92040b3 Mon Sep 17 00:00:00 2001 From: Cedric Date: Mon, 6 May 2024 17:49:09 +0100 Subject: [PATCH 44/45] [KS-90] Add database-backed store (#13045) * [KS-90] Add database-backed store * [KS-90] Add database-backed store --- core/services/chainlink/application.go | 4 + core/services/workflows/delegate.go | 7 +- core/services/workflows/engine.go | 236 +++++++---- core/services/workflows/engine_test.go | 258 +++++++++--- core/services/workflows/models.go | 3 +- core/services/workflows/state.go | 81 ++-- core/services/workflows/state_test.go | 109 ++--- core/services/workflows/store.go | 70 ---- core/services/workflows/store/models.go | 41 ++ core/services/workflows/store/store.go | 16 + core/services/workflows/store/store_db.go | 382 ++++++++++++++++++ .../services/workflows/store/store_db_test.go | 215 ++++++++++ core/services/workflows/store/store_memory.go | 86 ++++ .../migrations/0235_add_workflow_models.sql | 47 +++ 14 files changed, 1249 insertions(+), 306 deletions(-) delete mode 100644 core/services/workflows/store.go create mode 100644 core/services/workflows/store/models.go create mode 100644 core/services/workflows/store/store.go create mode 100644 core/services/workflows/store/store_db.go create mode 100644 core/services/workflows/store/store_db_test.go create mode 100644 core/services/workflows/store/store_memory.go create mode 100644 core/store/migrate/migrations/0235_add_workflow_models.sql diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index ae3db2e7a73..ef4b0d870dd 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -12,6 +12,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/google/uuid" "github.com/grafana/pyroscope-go" + "github.com/jonboulle/clockwork" "github.com/pkg/errors" "go.uber.org/multierr" "go.uber.org/zap/zapcore" @@ -63,6 +64,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/vrf" "github.com/smartcontractkit/chainlink/v2/core/services/webhook" "github.com/smartcontractkit/chainlink/v2/core/services/workflows" + workflowstore "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" "github.com/smartcontractkit/chainlink/v2/core/sessions" "github.com/smartcontractkit/chainlink/v2/core/sessions/ldapauth" "github.com/smartcontractkit/chainlink/v2/core/sessions/localauth" @@ -319,6 +321,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { jobORM = job.NewORM(opts.DS, pipelineORM, bridgeORM, keyStore, globalLogger) txmORM = txmgr.NewTxStore(opts.DS, globalLogger) streamRegistry = streams.NewRegistry(globalLogger, pipelineRunner) + workflowORM = workflowstore.NewDBStore(opts.DS, clockwork.NewRealClock()) ) for _, chain := range legacyEVMChains.Slice() { @@ -388,6 +391,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { globalLogger, registry, legacyEVMChains, + workflowORM, func() *p2ptypes.PeerID { if externalPeerWrapper == nil { return nil diff --git a/core/services/workflows/delegate.go b/core/services/workflows/delegate.go index 8dc440da477..9db802f9a2f 100644 --- a/core/services/workflows/delegate.go +++ b/core/services/workflows/delegate.go @@ -15,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" + "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" ) type Delegate struct { @@ -22,6 +23,7 @@ type Delegate struct { logger logger.Logger legacyEVMChains legacyevm.LegacyChainContainer peerID func() *p2ptypes.PeerID + store store.Store } var _ job.Delegate = (*Delegate)(nil) @@ -58,6 +60,7 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) ([]job.Ser Registry: d.registry, DONInfo: dinfo, PeerID: d.peerID, + Store: d.store, } engine, err := NewEngine(cfg) if err != nil { @@ -103,8 +106,8 @@ func initializeDONInfo(lggr logger.Logger) (*capabilities.DON, error) { }, nil } -func NewDelegate(logger logger.Logger, registry core.CapabilitiesRegistry, legacyEVMChains legacyevm.LegacyChainContainer, peerID func() *p2ptypes.PeerID) *Delegate { - return &Delegate{logger: logger, registry: registry, legacyEVMChains: legacyEVMChains, peerID: peerID} +func NewDelegate(logger logger.Logger, registry core.CapabilitiesRegistry, legacyEVMChains legacyevm.LegacyChainContainer, store store.Store, peerID func() *p2ptypes.PeerID) *Delegate { + return &Delegate{logger: logger, registry: registry, legacyEVMChains: legacyEVMChains, store: store, peerID: peerID} } func ValidatedWorkflowSpec(tomlString string) (job.Job, error) { diff --git a/core/services/workflows/engine.go b/core/services/workflows/engine.go index e405102e123..292ad9c6468 100644 --- a/core/services/workflows/engine.go +++ b/core/services/workflows/engine.go @@ -8,18 +8,20 @@ import ( "sync" "time" + "github.com/jonboulle/clockwork" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/types/core" "github.com/smartcontractkit/chainlink-common/pkg/values" "github.com/smartcontractkit/chainlink/v2/core/logger" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" + "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" ) const ( // NOTE: max 32 bytes per ID - consider enforcing exactly 32 bytes? - mockedTriggerID = "cccccccccc0000000000000000000000" - mockedWorkflowID = "15c631d295ef5e32deb99a10ee6804bc4af1385568f9b3363f6552ac6dbb2cef" + mockedTriggerID = "cccccccccc0000000000000000000000" ) type donInfo struct { @@ -30,18 +32,19 @@ type donInfo struct { // Engine handles the lifecycle of a single workflow and its executions. type Engine struct { services.StateMachine - logger logger.Logger - registry core.CapabilitiesRegistry - workflow *workflow - donInfo donInfo - executionStates *inMemoryStore - pendingStepRequests chan stepRequest - triggerEvents chan capabilities.CapabilityResponse - newWorkerCh chan struct{} - stepUpdateCh chan stepState - wg sync.WaitGroup - stopCh services.StopChan - newWorkerTimeout time.Duration + logger logger.Logger + registry core.CapabilitiesRegistry + workflow *workflow + donInfo donInfo + executionStates store.Store + pendingStepRequests chan stepRequest + triggerEvents chan capabilities.CapabilityResponse + newWorkerCh chan struct{} + stepUpdateCh chan store.WorkflowExecutionStep + wg sync.WaitGroup + stopCh services.StopChan + newWorkerTimeout time.Duration + maxExecutionDuration time.Duration // testing lifecycle hook to signal when an execution is finished. onExecutionFinished func(string) @@ -53,6 +56,8 @@ type Engine struct { // Used for testing to control the retry interval // when initializing the engine. retryMs int + + clock clockwork.Clock } func (e *Engine) Start(ctx context.Context) error { @@ -183,7 +188,13 @@ func (e *Engine) init(ctx context.Context) { return } - e.logger.Debug("capabilities resolved, registering triggers") + e.logger.Debug("capabilities resolved, resuming in-progress workflows") + err := e.resumeInProgressExecutions(ctx) + if err != nil { + e.logger.Errorf("failed to resume workflows: %w", err) + } + + e.logger.Debug("registering triggers") for _, t := range e.workflow.triggers { err := e.registerTrigger(ctx, t) if err != nil { @@ -195,6 +206,55 @@ func (e *Engine) init(ctx context.Context) { e.afterInit(true) } +var ( + defaultOffset, defaultLimit = 0, 1_000 +) + +func (e *Engine) resumeInProgressExecutions(ctx context.Context) error { + wipExecutions, err := e.executionStates.GetUnfinished(ctx, defaultOffset, defaultLimit) + if err != nil { + return err + } + + // TODO: paginate properly + if len(wipExecutions) >= defaultLimit { + e.logger.Warnf("possible execution overflow during resumption") + } + + // Cache the dependents associated with a step. + // We may have to reprocess many executions, but should only + // need to calculate the dependents of a step once since + // they won't change. + refToDeps := map[string][]*step{} + for _, execution := range wipExecutions { + for _, step := range execution.Steps { + // NOTE: In order to determine what tasks need to be enqueued, + // we look at any completed steps, and for each dependent, + // check if they are ready to be enqueued. + // This will also handle an execution that has stalled immediately on creation, + // since we always create an execution with an initially completed trigger step. + if step.Status != store.StatusCompleted { + continue + } + + sds, ok := refToDeps[step.Ref] + if !ok { + s, err := e.workflow.dependents(step.Ref) + if err != nil { + return err + } + + sds = s + } + + for _, sd := range sds { + e.queueIfReady(execution, sd) + } + } + } + return nil +} + // initializeExecutionStrategy for `step`. // Broadly speaking, we'll use `immediateExecution` for non-target steps // and `scheduledExecution` for targets. If we don't have the necessary @@ -341,12 +401,12 @@ func (e *Engine) loop(ctx context.Context) { // Wait for a new worker to be available before dispatching a new one. // We'll do this up to newWorkerTimeout. If this expires, we'll put the // message back on the queue and keep going. - t := time.NewTimer(e.newWorkerTimeout) + t := e.clock.NewTimer(e.newWorkerTimeout) select { case <-e.newWorkerCh: e.wg.Add(1) go e.workerForStepRequest(ctx, pendingStepRequest) - case <-t.C: + case <-t.Chan(): e.logger.Errorf("timed out when spinning off worker for pending step request %+v", pendingStepRequest) e.pendingStepRequests <- pendingStepRequest } @@ -379,21 +439,23 @@ func generateExecutionID(workflowID, eventID string) (string, error) { // startExecution kicks off a new workflow execution when a trigger event is received. func (e *Engine) startExecution(ctx context.Context, executionID string, event values.Value) error { e.logger.Debugw("executing on a trigger event", "event", event, "executionID", executionID) - ec := &executionState{ - steps: map[string]*stepState{ + ec := &store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ keywordTrigger: { - outputs: &stepOutput{ - value: event, + Outputs: &store.StepOutput{ + Value: event, }, - status: statusCompleted, + Status: store.StatusCompleted, + ExecutionID: executionID, + Ref: keywordTrigger, }, }, - workflowID: e.workflow.id, - executionID: executionID, - status: statusStarted, + WorkflowID: e.workflow.id, + ExecutionID: executionID, + Status: store.StatusStarted, } - err := e.executionStates.add(ctx, ec) + err := e.executionStates.Add(ctx, ec) if err != nil { return err } @@ -413,26 +475,25 @@ func (e *Engine) startExecution(ctx context.Context, executionID string, event v return nil } -func (e *Engine) handleStepUpdate(ctx context.Context, stepUpdate stepState) error { - state, err := e.executionStates.updateStep(ctx, &stepUpdate) +func (e *Engine) handleStepUpdate(ctx context.Context, stepUpdate store.WorkflowExecutionStep) error { + state, err := e.executionStates.UpsertStep(ctx, &stepUpdate) if err != nil { return err } - switch stepUpdate.status { - case statusCompleted: - stepDependents, err := e.workflow.dependents(stepUpdate.ref) + switch stepUpdate.Status { + case store.StatusCompleted: + stepDependents, err := e.workflow.dependents(stepUpdate.Ref) if err != nil { return err } // There are no steps left to process in the current path, so let's check if // we've completed the workflow. - // If not, we'll check for any dependents that are ready to process. if len(stepDependents) == 0 { workflowCompleted := true err := e.workflow.walkDo(keywordTrigger, func(s *step) error { - step, ok := state.steps[s.Ref] + step, ok := state.Steps[s.Ref] // The step is missing from the state, // which means it hasn't been processed yet. // Let's mark `workflowCompleted` = false, and @@ -442,8 +503,8 @@ func (e *Engine) handleStepUpdate(ctx context.Context, stepUpdate stepState) err return nil } - switch step.status { - case statusCompleted, statusErrored: + switch step.Status { + case store.StatusCompleted, store.StatusErrored: default: workflowCompleted = false } @@ -454,18 +515,23 @@ func (e *Engine) handleStepUpdate(ctx context.Context, stepUpdate stepState) err } if workflowCompleted { - err := e.finishExecution(ctx, state.executionID, statusCompleted) - if err != nil { - return err - } + return e.finishExecution(ctx, state.ExecutionID, store.StatusCompleted) } } + // We haven't completed the workflow, but should we continue? + // If we've been executing for too long, let's time the workflow out and stop here. + if state.CreatedAt != nil && e.clock.Since(*state.CreatedAt) > e.maxExecutionDuration { + return e.finishExecution(ctx, state.ExecutionID, store.StatusTimeout) + } + + // Finally, since the workflow hasn't timed out or completed, let's + // check for any dependents that are ready to process. for _, sd := range stepDependents { e.queueIfReady(state, sd) } - case statusErrored: - err := e.finishExecution(ctx, state.executionID, statusErrored) + case store.StatusErrored: + err := e.finishExecution(ctx, state.ExecutionID, store.StatusErrored) if err != nil { return err } @@ -474,11 +540,11 @@ func (e *Engine) handleStepUpdate(ctx context.Context, stepUpdate stepState) err return nil } -func (e *Engine) queueIfReady(state executionState, step *step) { +func (e *Engine) queueIfReady(state store.WorkflowExecution, step *step) { // Check if all dependencies are completed for the current step var waitingOnDependencies bool for _, dr := range step.dependencies { - stepState, ok := state.steps[dr] + stepState, ok := state.Steps[dr] if !ok { waitingOnDependencies = true continue @@ -489,7 +555,7 @@ func (e *Engine) queueIfReady(state executionState, step *step) { // This includes cases where one of the dependent // steps has errored, since that means we shouldn't // schedule the step for execution. - if stepState.status != statusCompleted { + if stepState.Status != store.StatusCompleted { waitingOnDependencies = true } } @@ -506,7 +572,7 @@ func (e *Engine) queueIfReady(state executionState, step *step) { func (e *Engine) finishExecution(ctx context.Context, executionID string, status string) error { e.logger.Infow("finishing execution", "executionID", executionID, "status", status) - err := e.executionStates.updateStatus(ctx, executionID, status) + err := e.executionStates.UpdateStatus(ctx, executionID, status) if err != nil { return err } @@ -521,27 +587,27 @@ func (e *Engine) workerForStepRequest(ctx context.Context, msg stepRequest) { // Instantiate a child logger; in addition to the WorkflowID field the workflow // logger will already have, this adds the `stepRef` and `executionID` - l := e.logger.With("stepRef", msg.stepRef, "executionID", msg.state.executionID) + l := e.logger.With("stepRef", msg.stepRef, "executionID", msg.state.ExecutionID) l.Debugw("executing on a step event") - stepState := &stepState{ - outputs: &stepOutput{}, - executionID: msg.state.executionID, - ref: msg.stepRef, + stepState := &store.WorkflowExecutionStep{ + Outputs: &store.StepOutput{}, + ExecutionID: msg.state.ExecutionID, + Ref: msg.stepRef, } inputs, outputs, err := e.executeStep(ctx, l, msg) if err != nil { l.Errorf("error executing step request: %s", err) - stepState.outputs.err = err - stepState.status = statusErrored + stepState.Outputs.Err = err + stepState.Status = store.StatusErrored } else { l.Infow("step executed successfully", "outputs", outputs) - stepState.outputs.value = outputs - stepState.status = statusCompleted + stepState.Outputs.Value = outputs + stepState.Status = store.StatusCompleted } - stepState.inputs = inputs + stepState.Inputs = inputs // Let's try and emit the stepUpdate. // If the context is canceled, we'll just drop the update. @@ -577,8 +643,8 @@ func (e *Engine) executeStep(ctx context.Context, l logger.Logger, msg stepReque Inputs: inputs, Config: step.config, Metadata: capabilities.RequestMetadata{ - WorkflowID: msg.state.workflowID, - WorkflowExecutionID: msg.state.executionID, + WorkflowID: msg.state.WorkflowID, + WorkflowExecutionID: msg.state.ExecutionID, }, } @@ -670,27 +736,31 @@ func (e *Engine) Close() error { } type Config struct { - Spec string - WorkflowID string - Lggr logger.Logger - Registry core.CapabilitiesRegistry - MaxWorkerLimit int - QueueSize int - NewWorkerTimeout time.Duration - DONInfo *capabilities.DON - PeerID func() *p2ptypes.PeerID + Spec string + WorkflowID string + Lggr logger.Logger + Registry core.CapabilitiesRegistry + MaxWorkerLimit int + QueueSize int + NewWorkerTimeout time.Duration + MaxExecutionDuration time.Duration + DONInfo *capabilities.DON + PeerID func() *p2ptypes.PeerID + Store store.Store // For testing purposes only maxRetries int retryMs int afterInit func(success bool) onExecutionFinished func(weid string) + clock clockwork.Clock } const ( - defaultWorkerLimit = 100 - defaultQueueSize = 100000 - defaultNewWorkerTimeout = 2 * time.Second + defaultWorkerLimit = 100 + defaultQueueSize = 100000 + defaultNewWorkerTimeout = 2 * time.Second + defaultMaxExecutionDuration = 10 * time.Minute ) func NewEngine(cfg Config) (engine *Engine, err error) { @@ -706,6 +776,14 @@ func NewEngine(cfg Config) (engine *Engine, err error) { cfg.NewWorkerTimeout = defaultNewWorkerTimeout } + if cfg.MaxExecutionDuration == 0 { + cfg.MaxExecutionDuration = defaultMaxExecutionDuration + } + + if cfg.Store == nil { + cfg.Store = store.NewInMemoryStore() + } + if cfg.retryMs == 0 { cfg.retryMs = 5000 } @@ -718,6 +796,10 @@ func NewEngine(cfg Config) (engine *Engine, err error) { cfg.onExecutionFinished = func(weid string) {} } + if cfg.clock == nil { + cfg.clock = clockwork.NewRealClock() + } + // TODO: validation of the workflow spec // We'll need to check, among other things: // - that there are no step `ref` called `trigger` as this is reserved for any triggers @@ -747,18 +829,20 @@ func NewEngine(cfg Config) (engine *Engine, err error) { DON: cfg.DONInfo, PeerID: cfg.PeerID, }, - executionStates: newInMemoryStore(), - pendingStepRequests: make(chan stepRequest, cfg.QueueSize), - newWorkerCh: newWorkerCh, - stepUpdateCh: make(chan stepState), - triggerEvents: make(chan capabilities.CapabilityResponse), - stopCh: make(chan struct{}), - newWorkerTimeout: cfg.NewWorkerTimeout, + executionStates: cfg.Store, + pendingStepRequests: make(chan stepRequest, cfg.QueueSize), + newWorkerCh: newWorkerCh, + stepUpdateCh: make(chan store.WorkflowExecutionStep), + triggerEvents: make(chan capabilities.CapabilityResponse), + stopCh: make(chan struct{}), + newWorkerTimeout: cfg.NewWorkerTimeout, + maxExecutionDuration: cfg.MaxExecutionDuration, onExecutionFinished: cfg.onExecutionFinished, afterInit: cfg.afterInit, maxRetries: cfg.maxRetries, retryMs: cfg.retryMs, + clock: cfg.clock, } return engine, nil } diff --git a/core/services/workflows/engine_test.go b/core/services/workflows/engine_test.go index ff4c5682129..212ad37367e 100644 --- a/core/services/workflows/engine_test.go +++ b/core/services/workflows/engine_test.go @@ -4,7 +4,9 @@ import ( "context" "errors" "testing" + "time" + "github.com/jonboulle/clockwork" "github.com/shopspring/decimal" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -13,8 +15,10 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/values" coreCap "github.com/smartcontractkit/chainlink/v2/core/capabilities" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" + "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" ) const hardcodedWorkflow = ` @@ -71,7 +75,7 @@ type testHooks struct { } // newTestEngine creates a new engine with some test defaults. -func newTestEngine(t *testing.T, reg *coreCap.Registry, spec string) (*Engine, *testHooks) { +func newTestEngine(t *testing.T, reg *coreCap.Registry, spec string, opts ...func(c *Config)) (*Engine, *testHooks) { peerID := p2ptypes.PeerID{} initFailed := make(chan struct{}) executionFinished := make(chan string, 100) @@ -91,6 +95,10 @@ func newTestEngine(t *testing.T, reg *coreCap.Registry, spec string) (*Engine, * onExecutionFinished: func(weid string) { executionFinished <- weid }, + clock: clockwork.NewFakeClock(), + } + for _, o := range opts { + o(&cfg) } eng, err := NewEngine(cfg) require.NoError(t, err) @@ -152,14 +160,16 @@ func (m *mockCapability) UnregisterFromWorkflow(ctx context.Context, request cap type mockTriggerCapability struct { capabilities.CapabilityInfo - triggerEvent capabilities.CapabilityResponse + triggerEvent *capabilities.CapabilityResponse ch chan capabilities.CapabilityResponse } var _ capabilities.TriggerCapability = (*mockTriggerCapability)(nil) func (m *mockTriggerCapability) RegisterTrigger(ctx context.Context, req capabilities.CapabilityRequest) (<-chan capabilities.CapabilityResponse, error) { - m.ch <- m.triggerEvent + if m.triggerEvent != nil { + m.ch <- *m.triggerEvent + } return m.ch, nil } @@ -169,47 +179,70 @@ func (m *mockTriggerCapability) UnregisterTrigger(ctx context.Context, req capab func TestEngineWithHardcodedWorkflow(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) - reg := coreCap.NewRegistry(logger.TestLogger(t)) - trigger, cr := mockTrigger(t) - - require.NoError(t, reg.Add(ctx, trigger)) - require.NoError(t, reg.Add(ctx, mockConsensus())) - target1 := mockTarget() - require.NoError(t, reg.Add(ctx, target1)) - - target2 := newMockCapability( - capabilities.MustNewCapabilityInfo( - "write_ethereum-testnet-sepolia", - capabilities.CapabilityTypeTarget, - "a write capability targeting ethereum sepolia testnet", - "v1.0.0", - nil, - ), - func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { - m := req.Inputs.Underlying["report"].(*values.Map) - return capabilities.CapabilityResponse{ - Value: m, - }, nil + testCases := []struct { + name string + store store.Store + }{ + { + name: "db-engine", + store: store.NewDBStore(pgtest.NewSqlxDB(t), clockwork.NewFakeClock()), }, - ) - require.NoError(t, reg.Add(ctx, target2)) - - eng, hooks := newTestEngine(t, reg, hardcodedWorkflow) - - err := eng.Start(ctx) - require.NoError(t, err) - defer eng.Close() - - eid := getExecutionId(t, eng, hooks) - assert.Equal(t, cr, <-target1.response) - assert.Equal(t, cr, <-target2.response) - - state, err := eng.executionStates.get(ctx, eid) - require.NoError(t, err) - - assert.Equal(t, state.status, statusCompleted) + { + name: "in-memory-engine", + store: store.NewInMemoryStore(), + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + ctx := testutils.Context(t) + reg := coreCap.NewRegistry(logger.TestLogger(t)) + + trigger, cr := mockTrigger(t) + + require.NoError(t, reg.Add(ctx, trigger)) + require.NoError(t, reg.Add(ctx, mockConsensus())) + target1 := mockTarget() + require.NoError(t, reg.Add(ctx, target1)) + + target2 := newMockCapability( + capabilities.MustNewCapabilityInfo( + "write_ethereum-testnet-sepolia", + capabilities.CapabilityTypeTarget, + "a write capability targeting ethereum sepolia testnet", + "v1.0.0", + nil, + ), + func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { + m := req.Inputs.Underlying["report"].(*values.Map) + return capabilities.CapabilityResponse{ + Value: m, + }, nil + }, + ) + require.NoError(t, reg.Add(ctx, target2)) + + eng, testHooks := newTestEngine( + t, + reg, + hardcodedWorkflow, + func(c *Config) { c.Store = tc.store }, + ) + + err := eng.Start(ctx) + require.NoError(t, err) + defer eng.Close() + + eid := getExecutionId(t, eng, testHooks) + assert.Equal(t, cr, <-target1.response) + assert.Equal(t, cr, <-target2.response) + + state, err := eng.executionStates.Get(ctx, eid) + require.NoError(t, err) + + assert.Equal(t, state.Status, store.StatusCompleted) + }) + } } const ( @@ -275,10 +308,24 @@ func mockTrigger(t *testing.T) (capabilities.TriggerCapability, capabilities.Cap cr := capabilities.CapabilityResponse{ Value: resp, } - mt.triggerEvent = cr + mt.triggerEvent = &cr return mt, cr } +func mockNoopTrigger(t *testing.T) capabilities.TriggerCapability { + mt := &mockTriggerCapability{ + CapabilityInfo: capabilities.MustNewCapabilityInfo( + "mercury-trigger", + capabilities.CapabilityTypeTrigger, + "issues a trigger when a mercury report is received.", + "v1.0.0", + nil, + ), + ch: make(chan capabilities.CapabilityResponse, 10), + } + return mt +} + func mockFailingConsensus() *mockCapability { return newMockCapability( capabilities.MustNewCapabilityInfo( @@ -357,12 +404,12 @@ func TestEngine_ErrorsTheWorkflowIfAStepErrors(t *testing.T) { defer eng.Close() eid := getExecutionId(t, eng, hooks) - state, err := eng.executionStates.get(ctx, eid) + state, err := eng.executionStates.Get(ctx, eid) require.NoError(t, err) - assert.Equal(t, state.status, statusErrored) + assert.Equal(t, state.Status, store.StatusErrored) // evm_median is the ref of our failing consensus step - assert.Equal(t, state.steps["evm_median"].status, statusErrored) + assert.Equal(t, state.Steps["evm_median"].Status, store.StatusErrored) } const ( @@ -455,14 +502,14 @@ func TestEngine_MultiStepDependencies(t *testing.T) { defer eng.Close() eid := getExecutionId(t, eng, hooks) - state, err := eng.executionStates.get(ctx, eid) + state, err := eng.executionStates.Get(ctx, eid) require.NoError(t, err) - assert.Equal(t, state.status, statusCompleted) + assert.Equal(t, state.Status, store.StatusCompleted) // The inputs to the consensus step should // be the outputs of the two dependents. - inputs := state.steps["evm_median"].inputs + inputs := state.Steps["evm_median"].Inputs unw, err := values.Unwrap(inputs) require.NoError(t, err) @@ -477,3 +524,116 @@ func TestEngine_MultiStepDependencies(t *testing.T) { require.NoError(t, err) assert.Equal(t, obs.([]any)[1], o) } + +func TestEngine_ResumesPendingExecutions(t *testing.T) { + t.Parallel() + ctx := testutils.Context(t) + reg := coreCap.NewRegistry(logger.TestLogger(t)) + + trigger := mockNoopTrigger(t) + resp, err := values.NewMap(map[string]any{ + "123": decimal.NewFromFloat(1.00), + "456": decimal.NewFromFloat(1.25), + "789": decimal.NewFromFloat(1.50), + }) + require.NoError(t, err) + + require.NoError(t, reg.Add(ctx, trigger)) + require.NoError(t, reg.Add(ctx, mockConsensus())) + require.NoError(t, reg.Add(ctx, mockTarget())) + + action, _ := mockAction() + require.NoError(t, reg.Add(ctx, action)) + + dbstore := store.NewDBStore(pgtest.NewSqlxDB(t), clockwork.NewFakeClock()) + ec := &store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ + keywordTrigger: { + Outputs: &store.StepOutput{ + Value: resp, + }, + Status: store.StatusCompleted, + ExecutionID: "", + Ref: keywordTrigger, + }, + }, + WorkflowID: "", + ExecutionID: "", + Status: store.StatusStarted, + } + err = dbstore.Add(ctx, ec) + require.NoError(t, err) + + eng, hooks := newTestEngine( + t, + reg, + multiStepWorkflow, + func(c *Config) { c.Store = dbstore }, + ) + err = eng.Start(ctx) + require.NoError(t, err) + + eid := getExecutionId(t, eng, hooks) + gotEx, err := dbstore.Get(ctx, eid) + require.NoError(t, err) + assert.Equal(t, store.StatusCompleted, gotEx.Status) +} + +func TestEngine_TimesOutOldExecutions(t *testing.T) { + t.Parallel() + ctx := testutils.Context(t) + reg := coreCap.NewRegistry(logger.TestLogger(t)) + + trigger := mockNoopTrigger(t) + resp, err := values.NewMap(map[string]any{ + "123": decimal.NewFromFloat(1.00), + "456": decimal.NewFromFloat(1.25), + "789": decimal.NewFromFloat(1.50), + }) + require.NoError(t, err) + + require.NoError(t, reg.Add(ctx, trigger)) + require.NoError(t, reg.Add(ctx, mockConsensus())) + require.NoError(t, reg.Add(ctx, mockTarget())) + + action, _ := mockAction() + require.NoError(t, reg.Add(ctx, action)) + + clock := clockwork.NewFakeClock() + dbstore := store.NewDBStore(pgtest.NewSqlxDB(t), clock) + ec := &store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ + keywordTrigger: { + Outputs: &store.StepOutput{ + Value: resp, + }, + Status: store.StatusCompleted, + ExecutionID: "", + Ref: keywordTrigger, + }, + }, + WorkflowID: "", + ExecutionID: "", + Status: store.StatusStarted, + } + err = dbstore.Add(ctx, ec) + require.NoError(t, err) + + eng, hooks := newTestEngine( + t, + reg, + multiStepWorkflow, + func(c *Config) { + c.Store = dbstore + c.clock = clock + }, + ) + clock.Advance(15 * time.Minute) + err = eng.Start(ctx) + require.NoError(t, err) + + _ = getExecutionId(t, eng, hooks) + gotEx, err := dbstore.Get(ctx, "") + require.NoError(t, err) + assert.Equal(t, store.StatusTimeout, gotEx.Status) +} diff --git a/core/services/workflows/models.go b/core/services/workflows/models.go index cd167403089..8dce11cabe5 100644 --- a/core/services/workflows/models.go +++ b/core/services/workflows/models.go @@ -8,11 +8,12 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" ) type stepRequest struct { stepRef string - state executionState + state store.WorkflowExecution } // stepDefinition is the parsed representation of a step in a workflow. diff --git a/core/services/workflows/state.go b/core/services/workflows/state.go index c229b14e1dd..4026a59be0b 100644 --- a/core/services/workflows/state.go +++ b/core/services/workflows/state.go @@ -6,71 +6,44 @@ import ( "strconv" "strings" - "github.com/smartcontractkit/chainlink-common/pkg/values" -) + "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" -const ( - statusStarted = "started" - statusErrored = "errored" - statusTimeout = "timeout" - statusCompleted = "completed" + "github.com/smartcontractkit/chainlink-common/pkg/values" ) -type stepOutput struct { - err error - value values.Value -} - -type stepState struct { - executionID string - ref string - status string - - inputs *values.Map - outputs *stepOutput -} - -type executionState struct { - steps map[string]*stepState - executionID string - workflowID string - - status string -} - // copyState returns a deep copy of the input executionState -func copyState(es executionState) executionState { - steps := map[string]*stepState{} - for ref, step := range es.steps { +func copyState(es store.WorkflowExecution) store.WorkflowExecution { + steps := map[string]*store.WorkflowExecutionStep{} + for ref, step := range es.Steps { var mval *values.Map - if step.inputs != nil { - mp := values.Proto(step.inputs).GetMapValue() + if step.Inputs != nil { + mp := values.Proto(step.Inputs).GetMapValue() mval = values.FromMapValueProto(mp) } - op := values.Proto(step.outputs.value) + op := values.Proto(step.Outputs.Value) copiedov := values.FromProto(op) - newState := &stepState{ - executionID: step.executionID, - ref: step.ref, - status: step.status, + newState := &store.WorkflowExecutionStep{ + ExecutionID: step.ExecutionID, + Ref: step.Ref, + Status: step.Status, - outputs: &stepOutput{ - err: step.outputs.err, - value: copiedov, + Outputs: &store.StepOutput{ + Err: step.Outputs.Err, + Value: copiedov, }, - inputs: mval, + Inputs: mval, } steps[ref] = newState } - return executionState{ - executionID: es.executionID, - workflowID: es.workflowID, - status: es.status, - steps: steps, + return store.WorkflowExecution{ + ExecutionID: es.ExecutionID, + WorkflowID: es.WorkflowID, + Status: es.Status, + Steps: steps, } } @@ -84,7 +57,7 @@ func copyState(es executionState) executionState { // If a key has more than two parts, then we traverse the parts // to find the value we want to replace. // We support traversing both nested maps and lists and any combination of the two. -func interpolateKey(key string, state executionState) (any, error) { +func interpolateKey(key string, state store.WorkflowExecution) (any, error) { parts := strings.Split(key, ".") if len(parts) < 2 { @@ -92,7 +65,7 @@ func interpolateKey(key string, state executionState) (any, error) { } // lookup the step we want to get either input or output state from - sc, ok := state.steps[parts[0]] + sc, ok := state.Steps[parts[0]] if !ok { return "", fmt.Errorf("could not find ref `%s`", parts[0]) } @@ -100,13 +73,13 @@ func interpolateKey(key string, state executionState) (any, error) { var value values.Value switch parts[1] { case "inputs": - value = sc.inputs + value = sc.Inputs case "outputs": - if sc.outputs.err != nil { + if sc.Outputs.Err != nil { return "", fmt.Errorf("cannot interpolate ref part `%s` in `%+v`: step has errored", parts[1], sc) } - value = sc.outputs.value + value = sc.Outputs.Value default: return "", fmt.Errorf("cannot interpolate ref part `%s` in `%+v`: second part must be `inputs` or `outputs`", parts[1], sc) } @@ -153,7 +126,7 @@ var ( // identifies any values that should be replaced from `state`. // // A value `v` should be replaced if it is wrapped as follows: `$(v)`. -func findAndInterpolateAllKeys(input any, state executionState) (any, error) { +func findAndInterpolateAllKeys(input any, state store.WorkflowExecution) (any, error) { return deepMap( input, func(el string) (any, error) { diff --git a/core/services/workflows/state_test.go b/core/services/workflows/state_test.go index 0917662ccb6..ccd6cd5004d 100644 --- a/core/services/workflows/state_test.go +++ b/core/services/workflows/state_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" ) func TestInterpolateKey(t *testing.T) { @@ -27,18 +28,18 @@ func TestInterpolateKey(t *testing.T) { testCases := []struct { name string key string - state executionState + state store.WorkflowExecution expected any errMsg string }{ { name: "digging into a string", key: "evm_median.outputs.reports", - state: executionState{ - steps: map[string]*stepState{ + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ "evm_median": { - outputs: &stepOutput{ - value: values.NewString(""), + Outputs: &store.StepOutput{ + Value: values.NewString(""), }, }, }, @@ -48,27 +49,27 @@ func TestInterpolateKey(t *testing.T) { { name: "ref doesn't exist", key: "evm_median.outputs.reports", - state: executionState{ - steps: map[string]*stepState{}, + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{}, }, errMsg: "could not find ref `evm_median`", }, { name: "less than 2 parts", key: "evm_median", - state: executionState{ - steps: map[string]*stepState{}, + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{}, }, errMsg: "must have at least two parts", }, { name: "second part isn't `inputs` or `outputs`", key: "evm_median.foo", - state: executionState{ - steps: map[string]*stepState{ + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ "evm_median": { - outputs: &stepOutput{ - value: values.NewString(""), + Outputs: &store.StepOutput{ + Value: values.NewString(""), }, }, }, @@ -78,11 +79,11 @@ func TestInterpolateKey(t *testing.T) { { name: "outputs has errored", key: "evm_median.outputs", - state: executionState{ - steps: map[string]*stepState{ + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ "evm_median": { - outputs: &stepOutput{ - err: errors.New("catastrophic error"), + Outputs: &store.StepOutput{ + Err: errors.New("catastrophic error"), }, }, }, @@ -92,11 +93,11 @@ func TestInterpolateKey(t *testing.T) { { name: "digging into a recursive map", key: "evm_median.outputs.reports.inner", - state: executionState{ - steps: map[string]*stepState{ + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ "evm_median": { - outputs: &stepOutput{ - value: val, + Outputs: &store.StepOutput{ + Value: val, }, }, }, @@ -106,11 +107,11 @@ func TestInterpolateKey(t *testing.T) { { name: "missing key in map", key: "evm_median.outputs.reports.missing", - state: executionState{ - steps: map[string]*stepState{ + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ "evm_median": { - outputs: &stepOutput{ - value: val, + Outputs: &store.StepOutput{ + Value: val, }, }, }, @@ -120,11 +121,11 @@ func TestInterpolateKey(t *testing.T) { { name: "digging into an array", key: "evm_median.outputs.reportsList.0", - state: executionState{ - steps: map[string]*stepState{ + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ "evm_median": { - outputs: &stepOutput{ - value: val, + Outputs: &store.StepOutput{ + Value: val, }, }, }, @@ -134,11 +135,11 @@ func TestInterpolateKey(t *testing.T) { { name: "digging into an array that's too small", key: "evm_median.outputs.reportsList.2", - state: executionState{ - steps: map[string]*stepState{ + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ "evm_median": { - outputs: &stepOutput{ - value: val, + Outputs: &store.StepOutput{ + Value: val, }, }, }, @@ -148,11 +149,11 @@ func TestInterpolateKey(t *testing.T) { { name: "digging into an array with a string key", key: "evm_median.outputs.reportsList.notAString", - state: executionState{ - steps: map[string]*stepState{ + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ "evm_median": { - outputs: &stepOutput{ - value: val, + Outputs: &store.StepOutput{ + Value: val, }, }, }, @@ -162,11 +163,11 @@ func TestInterpolateKey(t *testing.T) { { name: "digging into an array with a negative index", key: "evm_median.outputs.reportsList.-1", - state: executionState{ - steps: map[string]*stepState{ + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ "evm_median": { - outputs: &stepOutput{ - value: val, + Outputs: &store.StepOutput{ + Value: val, }, }, }, @@ -176,11 +177,11 @@ func TestInterpolateKey(t *testing.T) { { name: "empty element", key: "evm_median.outputs..notAString", - state: executionState{ - steps: map[string]*stepState{ + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ "evm_median": { - outputs: &stepOutput{ - value: val, + Outputs: &store.StepOutput{ + Value: val, }, }, }, @@ -207,7 +208,7 @@ func TestInterpolateInputsFromState(t *testing.T) { testCases := []struct { name string inputs map[string]any - state executionState + state store.WorkflowExecution expected any errMsg string }{ @@ -218,11 +219,11 @@ func TestInterpolateInputsFromState(t *testing.T) { "shouldinterpolate": "$(evm_median.outputs)", }, }, - state: executionState{ - steps: map[string]*stepState{ + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ "evm_median": { - outputs: &stepOutput{ - value: values.NewString(""), + Outputs: &store.StepOutput{ + Value: values.NewString(""), }, }, }, @@ -238,11 +239,11 @@ func TestInterpolateInputsFromState(t *testing.T) { inputs: map[string]any{ "foo": "bar", }, - state: executionState{ - steps: map[string]*stepState{ + state: store.WorkflowExecution{ + Steps: map[string]*store.WorkflowExecutionStep{ "evm_median": { - outputs: &stepOutput{ - value: values.NewString(""), + Outputs: &store.StepOutput{ + Value: values.NewString(""), }, }, }, diff --git a/core/services/workflows/store.go b/core/services/workflows/store.go deleted file mode 100644 index d6ef72d39b9..00000000000 --- a/core/services/workflows/store.go +++ /dev/null @@ -1,70 +0,0 @@ -package workflows - -import ( - "context" - "fmt" - "sync" -) - -// `inMemoryStore` is a temporary in-memory -// equivalent of the database table that should persist -// workflow progress. -type inMemoryStore struct { - idToState map[string]*executionState - mu sync.RWMutex -} - -func newInMemoryStore() *inMemoryStore { - return &inMemoryStore{idToState: map[string]*executionState{}} -} - -// add adds a new execution state under the given executionID -func (s *inMemoryStore) add(ctx context.Context, state *executionState) error { - s.mu.Lock() - defer s.mu.Unlock() - _, ok := s.idToState[state.executionID] - if ok { - return fmt.Errorf("execution ID %s already exists in store", state.executionID) - } - - s.idToState[state.executionID] = state - return nil -} - -// updateStep updates a step for the given executionID -func (s *inMemoryStore) updateStep(ctx context.Context, step *stepState) (executionState, error) { - s.mu.Lock() - defer s.mu.Unlock() - state, ok := s.idToState[step.executionID] - if !ok { - return executionState{}, fmt.Errorf("could not find execution %s", step.executionID) - } - - state.steps[step.ref] = step - return *state, nil -} - -// updateStatus updates the status for the given executionID -func (s *inMemoryStore) updateStatus(ctx context.Context, executionID string, status string) error { - s.mu.Lock() - defer s.mu.Unlock() - state, ok := s.idToState[executionID] - if !ok { - return fmt.Errorf("could not find execution %s", executionID) - } - - state.status = status - return nil -} - -// get gets the state for the given executionID -func (s *inMemoryStore) get(ctx context.Context, executionID string) (executionState, error) { - s.mu.RLock() - defer s.mu.RUnlock() - state, ok := s.idToState[executionID] - if !ok { - return executionState{}, fmt.Errorf("could not find execution %s", executionID) - } - - return *state, nil -} diff --git a/core/services/workflows/store/models.go b/core/services/workflows/store/models.go new file mode 100644 index 00000000000..29a1df154de --- /dev/null +++ b/core/services/workflows/store/models.go @@ -0,0 +1,41 @@ +package store + +import ( + "time" + + "github.com/smartcontractkit/chainlink-common/pkg/values" +) + +const ( + StatusStarted = "started" + StatusErrored = "errored" + StatusTimeout = "timeout" + StatusCompleted = "completed" +) + +type StepOutput struct { + Err error + Value values.Value +} + +type WorkflowExecutionStep struct { + ExecutionID string + Ref string + Status string + + Inputs *values.Map + Outputs *StepOutput + + UpdatedAt *time.Time +} + +type WorkflowExecution struct { + Steps map[string]*WorkflowExecutionStep + ExecutionID string + WorkflowID string + + Status string + CreatedAt *time.Time + UpdatedAt *time.Time + FinishedAt *time.Time +} diff --git a/core/services/workflows/store/store.go b/core/services/workflows/store/store.go new file mode 100644 index 00000000000..e77050617ab --- /dev/null +++ b/core/services/workflows/store/store.go @@ -0,0 +1,16 @@ +package store + +import ( + "context" +) + +type Store interface { + Add(ctx context.Context, state *WorkflowExecution) error + UpsertStep(ctx context.Context, step *WorkflowExecutionStep) (WorkflowExecution, error) + UpdateStatus(ctx context.Context, executionID string, status string) error + Get(ctx context.Context, executionID string) (WorkflowExecution, error) + GetUnfinished(ctx context.Context, offset, limit int) ([]WorkflowExecution, error) +} + +var _ Store = (*InMemoryStore)(nil) +var _ Store = (*DBStore)(nil) diff --git a/core/services/workflows/store/store_db.go b/core/services/workflows/store/store_db.go new file mode 100644 index 00000000000..73acece5b18 --- /dev/null +++ b/core/services/workflows/store/store_db.go @@ -0,0 +1,382 @@ +package store + +import ( + "context" + "errors" + "fmt" + "time" + + "google.golang.org/protobuf/proto" + + "github.com/jmoiron/sqlx" + "github.com/jonboulle/clockwork" + + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + "github.com/smartcontractkit/chainlink-common/pkg/values" + valuespb "github.com/smartcontractkit/chainlink-common/pkg/values/pb" +) + +// `DBStore` is a postgres-backed +// data store that persists workflow progress. +type DBStore struct { + db sqlutil.DataSource + clock clockwork.Clock +} + +// `workflowExecutionRow` describes a row +// of the `workflow_executions` table +type workflowExecutionRow struct { + ID string + WorkflowID *string + Status string + CreatedAt *time.Time + UpdatedAt *time.Time + FinishedAt *time.Time +} + +// `workflowStepRow` describes a row +// of the `workflow_steps` table +type workflowStepRow struct { + ID uint + WorkflowExecutionID string `db:"workflow_execution_id"` + Ref string + Status string + Inputs []byte + OutputErr *string `db:"output_err"` + OutputValue []byte `db:"output_value"` + UpdatedAt *time.Time `db:"updated_at"` +} + +// `UpdateStatus` updates the status of the given workflow execution +func (d *DBStore) UpdateStatus(ctx context.Context, executionID string, status string) error { + sql := `UPDATE workflow_executions SET status = $1, updated_at = $2 WHERE id = $3` + + // If we're completing the workflow execution, let's also set a finished_at timestamp. + if status != StatusStarted { + sql = "UPDATE workflow_executions SET status = $1, updated_at = $2, finished_at = $2 WHERE id = $3" + } + _, err := d.db.ExecContext(ctx, sql, status, d.clock.Now(), executionID) + return err +} + +// `UpsertStep` updates the given step. This will correspond to an insert, or an update +// depending on whether a step with the ref already exists. +func (d *DBStore) UpsertStep(ctx context.Context, stepState *WorkflowExecutionStep) (WorkflowExecution, error) { + step, err := stateToStep(stepState) + if err != nil { + return WorkflowExecution{}, err + } + + err = d.upsertSteps(ctx, []workflowStepRow{step}) + if err != nil { + return WorkflowExecution{}, err + } + + return d.Get(ctx, step.WorkflowExecutionID) +} + +// `Get` fetches the ExecutionState from the database. +func (d *DBStore) Get(ctx context.Context, executionID string) (WorkflowExecution, error) { + wex := &workflowExecutionRow{} + err := d.db.GetContext(ctx, wex, `SELECT * FROM workflow_executions WHERE id = $1`, executionID) + if err != nil { + return WorkflowExecution{}, err + } + + ws := []workflowStepRow{} + err = d.db.SelectContext(ctx, &ws, `SELECT * FROM workflow_steps WHERE workflow_execution_id = $1`, wex.ID) + if err != nil { + return WorkflowExecution{}, err + } + + refToStep := map[string]*WorkflowExecutionStep{} + for _, s := range ws { + ss, err := stepToState(s) + if err != nil { + return WorkflowExecution{}, err + } + + refToStep[s.Ref] = ss + } + + var workflowID string + if wex.WorkflowID != nil { + workflowID = *wex.WorkflowID + } + + es := WorkflowExecution{ + ExecutionID: wex.ID, + WorkflowID: workflowID, + Status: wex.Status, + Steps: refToStep, + CreatedAt: wex.CreatedAt, + UpdatedAt: wex.UpdatedAt, + FinishedAt: wex.FinishedAt, + } + return es, nil +} + +func stepToState(step workflowStepRow) (*WorkflowExecutionStep, error) { + var inputs *values.Map + if len(step.Inputs) > 0 { + vmProto := &valuespb.Map{} + err := proto.Unmarshal(step.Inputs, vmProto) + if err != nil { + return nil, err + } + + inputs = values.FromMapValueProto(vmProto) + } + + var ( + outputErr error + outputs values.Value + ) + + if step.OutputErr != nil { + outputErr = errors.New(*step.OutputErr) + } + + if len(step.OutputValue) != 0 { + vProto := &valuespb.Value{} + err := proto.Unmarshal(step.OutputValue, vProto) + if err != nil { + return nil, err + } + + outputs = values.FromProto(vProto) + } + + var so *StepOutput + if outputErr != nil || outputs != nil { + so = &StepOutput{ + Err: outputErr, + Value: outputs, + } + } + + return &WorkflowExecutionStep{ + ExecutionID: step.WorkflowExecutionID, + Ref: step.Ref, + Status: step.Status, + Inputs: inputs, + Outputs: so, + }, nil +} + +func stateToStep(state *WorkflowExecutionStep) (workflowStepRow, error) { + var inpb []byte + if state.Inputs != nil { + p := values.Proto(state.Inputs).GetMapValue() + ib, err := proto.Marshal(p) + if err != nil { + return workflowStepRow{}, err + } + inpb = ib + } + + wsr := workflowStepRow{ + WorkflowExecutionID: state.ExecutionID, + Ref: state.Ref, + Status: state.Status, + Inputs: inpb, + } + + if state.Outputs == nil { + return wsr, nil + } + + if state.Outputs.Value != nil { + p := values.Proto(state.Outputs.Value) + ob, err := proto.Marshal(p) + if err != nil { + return workflowStepRow{}, err + } + + wsr.OutputValue = ob + } + + if state.Outputs.Err != nil { + errs := state.Outputs.Err.Error() + wsr.OutputErr = &errs + } + return wsr, nil +} + +// `Add` creates the relevant workflow_execution and workflow_step entries +// to persist the passed in ExecutionState. +func (d *DBStore) Add(ctx context.Context, state *WorkflowExecution) error { + return d.transact(ctx, func(db *DBStore) error { + var wid *string + if state.WorkflowID != "" { + wid = &state.WorkflowID + } + wex := &workflowExecutionRow{ + ID: state.ExecutionID, + WorkflowID: wid, + Status: state.Status, + } + err := db.insertWorkflowExecution(ctx, wex) + if err != nil { + return fmt.Errorf("could not insert workflow execution %s: %w", state.ExecutionID, err) + } + + ws := []workflowStepRow{} + for _, step := range state.Steps { + step, err := stateToStep(step) + if err != nil { + return err + } + ws = append(ws, step) + } + if len(ws) > 0 { + return db.upsertSteps(ctx, ws) + } + return nil + }) +} + +func (d *DBStore) upsertSteps(ctx context.Context, steps []workflowStepRow) error { + for _, s := range steps { + now := d.clock.Now() + s.UpdatedAt = &now + } + + sql := ` + INSERT INTO + workflow_steps(workflow_execution_id, ref, status, inputs, output_err, output_value, updated_at) + VALUES (:workflow_execution_id, :ref, :status, :inputs, :output_err, :output_value, :updated_at) + ON CONFLICT ON CONSTRAINT uniq_workflow_execution_id_ref + DO UPDATE SET + workflow_execution_id = EXCLUDED.workflow_execution_id, + ref = EXCLUDED.ref, + status = EXCLUDED.status, + inputs = EXCLUDED.inputs, + output_err = EXCLUDED.output_err, + output_value = EXCLUDED.output_value, + updated_at = EXCLUDED.updated_at; + ` + stmt, args, err := sqlx.Named(sql, steps) + if err != nil { + return err + } + stmt = d.db.Rebind(stmt) + _, err = d.db.ExecContext(ctx, stmt, args...) + return err +} + +func (d *DBStore) insertWorkflowExecution(ctx context.Context, execution *workflowExecutionRow) error { + sql := ` + INSERT INTO + workflow_executions(id, workflow_id, status, created_at) + VALUES ($1, $2, $3, $4) + ` + _, err := d.db.ExecContext(ctx, sql, execution.ID, execution.WorkflowID, execution.Status, d.clock.Now()) + return err +} + +func (d *DBStore) transact(ctx context.Context, fn func(*DBStore) error) error { + return sqlutil.Transact( + ctx, + func(ds sqlutil.DataSource) *DBStore { + return &DBStore{db: ds, clock: d.clock} + }, + d.db, + nil, + fn, + ) +} + +func (d *DBStore) GetUnfinished(ctx context.Context, offset, limit int) ([]WorkflowExecution, error) { + sql := ` + SELECT + workflow_steps.workflow_execution_id AS ws_workflow_execution_id, + workflow_steps.ref AS ws_ref, + workflow_steps.status AS ws_status, + workflow_steps.inputs AS ws_inputs, + workflow_steps.output_err AS ws_output_err, + workflow_steps.output_value AS ws_output_value, + workflow_steps.updated_at AS ws_updated_at, + workflow_executions.id AS we_id, + workflow_executions.workflow_id AS we_workflow_id, + workflow_executions.status AS we_status, + workflow_executions.created_at AS we_created_at, + workflow_executions.updated_at AS we_updated_at, + workflow_executions.finished_at AS we_finished_at + FROM workflow_executions + JOIN workflow_steps + ON workflow_steps.workflow_execution_id = workflow_executions.id + WHERE workflow_executions.status = $1 + ORDER BY workflow_executions.created_at DESC + LIMIT $2 + OFFSET $3 + ` + joinRecords := []struct { + // WorkflowExecutionStep fields + WSWorkflowExecutionID string `db:"ws_workflow_execution_id"` + WSRef string `db:"ws_ref"` + WSStatus string `db:"ws_status"` + WSInputs []byte `db:"ws_inputs"` + WSOutputErr *string `db:"ws_output_err"` + WSOutputValue []byte `db:"ws_output_value"` + WSUpdatedAt *time.Time `db:"ws_updated_at"` + + // WorkflowExecution fields + WEID string `db:"we_id"` + WEWorkflowID *string `db:"we_workflow_id"` + WEStatus string `db:"we_status"` + WECreatedAt *time.Time `db:"we_created_at"` + WEUpdatedAt *time.Time `db:"we_updated_at"` + WEFinishedAt *time.Time `db:"we_finished_at"` + }{} + err := d.db.SelectContext(ctx, &joinRecords, sql, StatusStarted, limit, offset) + if err != nil { + return []WorkflowExecution{}, err + } + + idToExecutionState := map[string]*WorkflowExecution{} + for _, jr := range joinRecords { + var wid string + if jr.WEWorkflowID != nil { + wid = *jr.WEWorkflowID + } + if _, ok := idToExecutionState[jr.WEID]; !ok { + idToExecutionState[jr.WEID] = &WorkflowExecution{ + ExecutionID: jr.WEID, + WorkflowID: wid, + Status: jr.WEStatus, + Steps: map[string]*WorkflowExecutionStep{}, + CreatedAt: jr.WECreatedAt, + UpdatedAt: jr.WEUpdatedAt, + FinishedAt: jr.WEFinishedAt, + } + } + + state, err := stepToState(workflowStepRow{ + WorkflowExecutionID: jr.WSWorkflowExecutionID, + Ref: jr.WSRef, + OutputErr: jr.WSOutputErr, + OutputValue: jr.WSOutputValue, + Inputs: jr.WSInputs, + Status: jr.WSStatus, + UpdatedAt: jr.WSUpdatedAt, + }) + if err != nil { + return nil, err + } + + es := idToExecutionState[jr.WEID] + es.Steps[state.Ref] = state + } + + states := []WorkflowExecution{} + for _, s := range idToExecutionState { + states = append(states, *s) + } + + return states, nil +} + +func NewDBStore(ds sqlutil.DataSource, clock clockwork.Clock) *DBStore { + return &DBStore{db: ds, clock: clock} +} diff --git a/core/services/workflows/store/store_db_test.go b/core/services/workflows/store/store_db_test.go new file mode 100644 index 00000000000..e41f4857363 --- /dev/null +++ b/core/services/workflows/store/store_db_test.go @@ -0,0 +1,215 @@ +package store + +import ( + "crypto/rand" + "encoding/hex" + "errors" + "testing" + + "github.com/jonboulle/clockwork" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" +) + +func randomID() string { + b := make([]byte, 32) + _, err := rand.Read(b) + if err != nil { + panic(err) + } + return hex.EncodeToString(b) +} + +func Test_StoreDB(t *testing.T) { + db := pgtest.NewSqlxDB(t) + store := &DBStore{db: db, clock: clockwork.NewFakeClock()} + + id := randomID() + es := WorkflowExecution{ + Steps: map[string]*WorkflowExecutionStep{ + "step1": { + ExecutionID: id, + Ref: "step1", + Status: "completed", + }, + "step2": { + ExecutionID: id, + Ref: "step2", + Status: "started", + }, + }, + ExecutionID: id, + Status: "started", + } + + err := store.Add(tests.Context(t), &es) + require.NoError(t, err) + + gotEs, err := store.Get(tests.Context(t), es.ExecutionID) + // Zero out the created at timestamp; this isn't present on `es` + // but is added by the db store. + gotEs.CreatedAt = nil + require.NoError(t, err) + assert.Equal(t, es, gotEs) +} + +func Test_StoreDB_DuplicateEntry(t *testing.T) { + db := pgtest.NewSqlxDB(t) + store := &DBStore{db: db, clock: clockwork.NewFakeClock()} + + id := randomID() + es := WorkflowExecution{ + Steps: map[string]*WorkflowExecutionStep{ + "step1": { + ExecutionID: id, + Ref: "step1", + Status: "completed", + }, + "step2": { + ExecutionID: id, + Ref: "step2", + Status: "started", + }, + }, + ExecutionID: id, + Status: "started", + } + + err := store.Add(tests.Context(t), &es) + require.NoError(t, err) + + err = store.Add(tests.Context(t), &es) + assert.ErrorContains(t, err, "duplicate key value violates") +} + +func Test_StoreDB_UpdateStatus(t *testing.T) { + db := pgtest.NewSqlxDB(t) + store := &DBStore{db: db, clock: clockwork.NewFakeClock()} + + id := randomID() + es := WorkflowExecution{ + Steps: map[string]*WorkflowExecutionStep{ + "step1": { + ExecutionID: id, + Ref: "step1", + Status: "completed", + }, + "step2": { + ExecutionID: id, + Ref: "step2", + Status: "started", + }, + }, + ExecutionID: id, + Status: "started", + } + + err := store.Add(tests.Context(t), &es) + require.NoError(t, err) + + completedStatus := "completed" + err = store.UpdateStatus(tests.Context(t), es.ExecutionID, "completed") + require.NoError(t, err) + + gotEs, err := store.Get(tests.Context(t), es.ExecutionID) + require.NoError(t, err) + + assert.Equal(t, gotEs.Status, completedStatus) +} + +func Test_StoreDB_UpdateStep(t *testing.T) { + db := pgtest.NewSqlxDB(t) + store := &DBStore{db: db, clock: clockwork.NewFakeClock()} + + id := randomID() + stepOne := &WorkflowExecutionStep{ + ExecutionID: id, + Ref: "step1", + Status: "completed", + } + stepTwo := &WorkflowExecutionStep{ + ExecutionID: id, + Ref: "step2", + Status: "started", + } + es := WorkflowExecution{ + Steps: map[string]*WorkflowExecutionStep{ + "step1": stepOne, + "step2": stepTwo, + }, + ExecutionID: id, + Status: "started", + } + + err := store.Add(tests.Context(t), &es) + require.NoError(t, err) + + stepOne.Status = "completed" + nm, err := values.NewMap(map[string]any{"hello": "world"}) + require.NoError(t, err) + + stepOne.Inputs = nm + stepOne.Outputs = &StepOutput{Err: errors.New("some error")} + + es, err = store.UpsertStep(tests.Context(t), stepOne) + require.NoError(t, err) + + gotStep := es.Steps[stepOne.Ref] + assert.Equal(t, stepOne, gotStep) + + stepTwo.Outputs = &StepOutput{Value: nm} + es, err = store.UpsertStep(tests.Context(t), stepTwo) + require.NoError(t, err) + + gotStep = es.Steps[stepTwo.Ref] + assert.Equal(t, stepTwo, gotStep) +} + +func Test_StoreDB_GetUnfinishedSteps(t *testing.T) { + db := pgtest.NewSqlxDB(t) + store := &DBStore{db: db, clock: clockwork.NewFakeClock()} + + id := randomID() + stepOne := &WorkflowExecutionStep{ + ExecutionID: id, + Ref: "step1", + Status: "completed", + } + stepTwo := &WorkflowExecutionStep{ + ExecutionID: id, + Ref: "step2", + Status: "started", + } + es := WorkflowExecution{ + Steps: map[string]*WorkflowExecutionStep{ + "step1": stepOne, + "step2": stepTwo, + }, + ExecutionID: id, + Status: "started", + } + + err := store.Add(tests.Context(t), &es) + require.NoError(t, err) + + id = randomID() + esTwo := WorkflowExecution{ + ExecutionID: id, + Status: "completed", + Steps: map[string]*WorkflowExecutionStep{}, + } + err = store.Add(tests.Context(t), &esTwo) + require.NoError(t, err) + + states, err := store.GetUnfinished(tests.Context(t), 0, 100) + require.NoError(t, err) + + assert.Len(t, states, 1) + // Zero out the completedAt timestamp + states[0].CreatedAt = nil + assert.Equal(t, es, states[0]) +} diff --git a/core/services/workflows/store/store_memory.go b/core/services/workflows/store/store_memory.go new file mode 100644 index 00000000000..7c8226c5d9c --- /dev/null +++ b/core/services/workflows/store/store_memory.go @@ -0,0 +1,86 @@ +package store + +import ( + "context" + "fmt" + "sync" +) + +// `InMemoryStore` is a temporary in-memory +// equivalent of the database table that should persist +// workflow progress. +type InMemoryStore struct { + idToState map[string]*WorkflowExecution + mu sync.RWMutex +} + +func NewInMemoryStore() *InMemoryStore { + return &InMemoryStore{idToState: map[string]*WorkflowExecution{}} +} + +// Add adds a new execution state under the given executionID +func (s *InMemoryStore) Add(ctx context.Context, state *WorkflowExecution) error { + s.mu.Lock() + defer s.mu.Unlock() + _, ok := s.idToState[state.ExecutionID] + if ok { + return fmt.Errorf("execution ID %s already exists in store", state.ExecutionID) + } + + s.idToState[state.ExecutionID] = state + return nil +} + +// UpsertStep updates a step for the given executionID +func (s *InMemoryStore) UpsertStep(ctx context.Context, step *WorkflowExecutionStep) (WorkflowExecution, error) { + s.mu.Lock() + defer s.mu.Unlock() + state, ok := s.idToState[step.ExecutionID] + if !ok { + return WorkflowExecution{}, fmt.Errorf("could not find execution %s", step.ExecutionID) + } + + state.Steps[step.Ref] = step + return *state, nil +} + +// UpdateStatus updates the status for the given executionID +func (s *InMemoryStore) UpdateStatus(ctx context.Context, executionID string, status string) error { + s.mu.Lock() + defer s.mu.Unlock() + state, ok := s.idToState[executionID] + if !ok { + return fmt.Errorf("could not find execution %s", executionID) + } + + state.Status = status + return nil +} + +// Get gets the state for the given executionID +func (s *InMemoryStore) Get(ctx context.Context, executionID string) (WorkflowExecution, error) { + s.mu.RLock() + defer s.mu.RUnlock() + state, ok := s.idToState[executionID] + if !ok { + return WorkflowExecution{}, fmt.Errorf("could not find execution %s", executionID) + } + + return *state, nil +} + +// GetUnfinished gets the states for execution that are in a started state +// Offset and limit are ignored for the in-memory store. +func (s *InMemoryStore) GetUnfinished(ctx context.Context, offset, limit int) ([]WorkflowExecution, error) { + s.mu.RLock() + defer s.mu.RUnlock() + + states := []WorkflowExecution{} + for _, s := range s.idToState { + if s.Status == StatusStarted { + states = append(states, *s) + } + } + + return states, nil +} diff --git a/core/store/migrate/migrations/0235_add_workflow_models.sql b/core/store/migrate/migrations/0235_add_workflow_models.sql new file mode 100644 index 00000000000..bd159b3a9d2 --- /dev/null +++ b/core/store/migrate/migrations/0235_add_workflow_models.sql @@ -0,0 +1,47 @@ +-- +goose Up +-- +goose StatementBegin +CREATE TYPE workflow_status AS ENUM ( + 'started', + 'errored', + 'timeout', + 'completed' +); + +ALTER TABLE workflow_specs + ADD CONSTRAINT fk_unique_workflow_id unique(workflow_id); + +CREATE TABLE workflow_executions ( + id varchar(64) PRIMARY KEY, + workflow_id varchar(64) references workflow_specs(workflow_id), + status workflow_status NOT NULL, + created_at timestamp with time zone, + updated_at timestamp with time zone, + finished_at timestamp with time zone +); + +CREATE TABLE workflow_steps ( + id SERIAL PRIMARY KEY, + workflow_execution_id varchar(64) references workflow_executions(id) NOT NULL, + ref text NOT NULL, + status workflow_status NOT NULL, + inputs bytea, + output_err text, + output_value bytea, + updated_at timestamp with time zone +); + +ALTER TABLE workflow_steps + ADD CONSTRAINT uniq_workflow_execution_id_ref unique(workflow_execution_id, ref); + +-- +goose StatementEnd + +-- +goose Down +-- +goose StatementBegin +ALTER TABLE workflow_steps + DROP CONSTRAINT uniq_workflow_execution_id_ref; +DROP TABLE workflow_steps; +DROP TABLE workflow_executions; +ALTER TABLE workflow_specs + DROP CONSTRAINT fk_unique_workflow_id; +DROP TYPE workflow_status; +-- +goose StatementEnd From 466d1617607712263657029adf7ff4dd9713b3b3 Mon Sep 17 00:00:00 2001 From: Dylan Tinianov Date: Mon, 6 May 2024 13:30:35 -0400 Subject: [PATCH 45/45] Fix race condition in Poller tests (#13110) * Create polling channel * Update poller_test.go --- common/client/poller.go | 8 +++++--- common/client/poller_test.go | 40 ++++++++---------------------------- 2 files changed, 14 insertions(+), 34 deletions(-) diff --git a/common/client/poller.go b/common/client/poller.go index ebdcbd66283..d6080722c5c 100644 --- a/common/client/poller.go +++ b/common/client/poller.go @@ -27,10 +27,11 @@ type Poller[T any] struct { wg sync.WaitGroup } -// NewPoller creates a new Poller instance +// NewPoller creates a new Poller instance and returns a channel to receive the polled data func NewPoller[ T any, -](pollingInterval time.Duration, pollingFunc func(ctx context.Context) (T, error), pollingTimeout time.Duration, channel chan<- T, logger logger.Logger) Poller[T] { +](pollingInterval time.Duration, pollingFunc func(ctx context.Context) (T, error), pollingTimeout time.Duration, logger logger.Logger) (Poller[T], <-chan T) { + channel := make(chan T) return Poller[T]{ pollingInterval: pollingInterval, pollingFunc: pollingFunc, @@ -39,7 +40,7 @@ func NewPoller[ logger: logger, errCh: make(chan error), stopCh: make(chan struct{}), - } + }, channel } var _ types.Subscription = &Poller[any]{} @@ -58,6 +59,7 @@ func (p *Poller[T]) Unsubscribe() { close(p.stopCh) p.wg.Wait() close(p.errCh) + close(p.channel) return nil }) } diff --git a/common/client/poller_test.go b/common/client/poller_test.go index 3f11c759adb..82a05b5dfc7 100644 --- a/common/client/poller_test.go +++ b/common/client/poller_test.go @@ -23,10 +23,7 @@ func Test_Poller(t *testing.T) { return nil, nil } - channel := make(chan Head, 1) - defer close(channel) - - poller := NewPoller[Head](time.Millisecond, pollFunc, time.Second, channel, lggr) + poller, _ := NewPoller[Head](time.Millisecond, pollFunc, time.Second, lggr) err := poller.Start() require.NoError(t, err) @@ -50,12 +47,8 @@ func Test_Poller(t *testing.T) { return h.ToMockHead(t), nil } - // data channel to receive updates from the poller - channel := make(chan Head, 1) - defer close(channel) - // Create poller and start to receive data - poller := NewPoller[Head](time.Millisecond, pollFunc, time.Second, channel, lggr) + poller, channel := NewPoller[Head](time.Millisecond, pollFunc, time.Second, lggr) require.NoError(t, poller.Start()) defer poller.Unsubscribe() @@ -79,14 +72,10 @@ func Test_Poller(t *testing.T) { return nil, fmt.Errorf("polling error %d", pollNumber) } - // data channel to receive updates from the poller - channel := make(chan Head, 1) - defer close(channel) - olggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) // Create poller and subscribe to receive data - poller := NewPoller[Head](time.Millisecond, pollFunc, time.Second, channel, olggr) + poller, _ := NewPoller[Head](time.Millisecond, pollFunc, time.Second, olggr) require.NoError(t, poller.Start()) defer poller.Unsubscribe() @@ -114,14 +103,10 @@ func Test_Poller(t *testing.T) { // Set instant timeout pollingTimeout := time.Duration(0) - // data channel to receive updates from the poller - channel := make(chan Head, 1) - defer close(channel) - olggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) // Create poller and subscribe to receive data - poller := NewPoller[Head](time.Millisecond, pollFunc, pollingTimeout, channel, olggr) + poller, _ := NewPoller[Head](time.Millisecond, pollFunc, pollingTimeout, olggr) require.NoError(t, poller.Start()) defer poller.Unsubscribe() @@ -146,14 +131,10 @@ func Test_Poller(t *testing.T) { // Set long timeout pollingTimeout := time.Minute - // data channel to receive updates from the poller - channel := make(chan Head, 1) - defer close(channel) - olggr, observedLogs := logger.TestObserved(t, zap.WarnLevel) // Create poller and subscribe to receive data - poller := NewPoller[Head](time.Millisecond, pollFunc, pollingTimeout, channel, olggr) + poller, _ := NewPoller[Head](time.Millisecond, pollFunc, pollingTimeout, olggr) require.NoError(t, poller.Start()) // Unsubscribe while blocked in polling function @@ -184,8 +165,7 @@ func Test_Poller_Unsubscribe(t *testing.T) { } t.Run("Test multiple unsubscribe", func(t *testing.T) { - channel := make(chan Head, 1) - poller := NewPoller[Head](time.Millisecond, pollFunc, time.Second, channel, lggr) + poller, channel := NewPoller[Head](time.Millisecond, pollFunc, time.Second, lggr) err := poller.Start() require.NoError(t, err) @@ -194,14 +174,12 @@ func Test_Poller_Unsubscribe(t *testing.T) { poller.Unsubscribe() }) - t.Run("Test unsubscribe with closed channel", func(t *testing.T) { - channel := make(chan Head, 1) - poller := NewPoller[Head](time.Millisecond, pollFunc, time.Second, channel, lggr) + t.Run("Read channel after unsubscribe", func(t *testing.T) { + poller, channel := NewPoller[Head](time.Millisecond, pollFunc, time.Second, lggr) err := poller.Start() require.NoError(t, err) - <-channel - close(channel) poller.Unsubscribe() + require.Equal(t, <-channel, nil) }) }