From 365c38be8b589d5ffa0b21755dcb40e2e4205652 Mon Sep 17 00:00:00 2001 From: Christopher Dimitri Sastropranoto Date: Thu, 25 Apr 2024 23:33:57 +0700 Subject: [PATCH] Add functions to add a node operator (#12906) * add functions to add node operator * update gethwrapper --- .changeset/two-countries-lay.md | 5 + contracts/.changeset/tender-jokes-do.md | 5 + .../src/v0.8/keystone/CapabilityRegistry.sol | 72 +++++- .../src/v0.8/keystone/test/BaseTest.t.sol | 22 ++ .../keystone/test/CapabilityRegistry.t.sol | 21 -- ...CapabilityRegistry_AddCapabilityTest.t.sol | 17 ++ ...abilityRegistry_AddNodeOperatorsTest.t.sol | 41 ++++ .../src/v0.8/keystone/test/Constants.t.sol | 13 ++ .../keystone_capability_registry.go | 210 ++++++++++++++++-- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 10 files changed, 361 insertions(+), 47 deletions(-) create mode 100644 .changeset/two-countries-lay.md create mode 100644 contracts/.changeset/tender-jokes-do.md create mode 100644 contracts/src/v0.8/keystone/test/BaseTest.t.sol delete mode 100644 contracts/src/v0.8/keystone/test/CapabilityRegistry.t.sol create mode 100644 contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol create mode 100644 contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodeOperatorsTest.t.sol create mode 100644 contracts/src/v0.8/keystone/test/Constants.t.sol diff --git a/.changeset/two-countries-lay.md b/.changeset/two-countries-lay.md new file mode 100644 index 00000000000..f3d78e6a2e6 --- /dev/null +++ b/.changeset/two-countries-lay.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +update keystone gethwrapper #internal diff --git a/contracts/.changeset/tender-jokes-do.md b/contracts/.changeset/tender-jokes-do.md new file mode 100644 index 00000000000..5500fe0ca00 --- /dev/null +++ b/contracts/.changeset/tender-jokes-do.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +Implement function to add node operators to the capability registry' diff --git a/contracts/src/v0.8/keystone/CapabilityRegistry.sol b/contracts/src/v0.8/keystone/CapabilityRegistry.sol index 7c870bed7fb..ad452f1606b 100644 --- a/contracts/src/v0.8/keystone/CapabilityRegistry.sol +++ b/contracts/src/v0.8/keystone/CapabilityRegistry.sol @@ -4,25 +4,73 @@ pragma solidity ^0.8.0; import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol"; import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; -struct Capability { - // Capability type, e.g. "data-streams-reports" - // bytes32(string); validation regex: ^[a-z0-9_\-:]{1,32}$ - // Not "type" because that's a reserved keyword in Solidity. - bytes32 capabilityType; - // Semver, e.g., "1.2.3" - // bytes32(string); must be valid Semver + max 32 characters. - bytes32 version; -} - contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { - mapping(bytes32 => Capability) private s_capabilities; + struct NodeOperator { + /// @notice The address of the admin that can manage a node + /// operator + address admin; + /// @notice Human readable name of a Node Operator managing the node + string name; + } + + struct Capability { + // Capability type, e.g. "data-streams-reports" + // bytes32(string); validation regex: ^[a-z0-9_\-:]{1,32}$ + // Not "type" because that's a reserved keyword in Solidity. + bytes32 capabilityType; + // Semver, e.g., "1.2.3" + // bytes32(string); must be valid Semver + max 32 characters. + bytes32 version; + } + + /// @notice This error is thrown when trying to set a node operator's + /// admin address to the zero address + error InvalidNodeOperatorAdmin(); + + /// @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 + /// operator + /// @param name The human readable name of the node operator + event NodeOperatorAdded(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); + mapping(bytes32 => Capability) private s_capabilities; + + /// @notice Mapping of node operators + mapping(uint256 nodeOperatorId => NodeOperator) private s_nodeOperators; + + /// @notice The latest node operator ID + /// @dev No getter for this as this is an implementation detail + uint256 private s_nodeOperatorId; + function typeAndVersion() external pure override returns (string memory) { return "CapabilityRegistry 1.0.0"; } + /// @notice Adds a list of node operators + /// @param nodeOperators List of node operators to add + function addNodeOperators(NodeOperator[] calldata nodeOperators) external onlyOwner { + for (uint256 i; i < nodeOperators.length; ++i) { + NodeOperator memory nodeOperator = nodeOperators[i]; + if (nodeOperator.admin == address(0)) revert InvalidNodeOperatorAdmin(); + uint256 nodeOperatorId = s_nodeOperatorId; + s_nodeOperators[nodeOperatorId] = NodeOperator({admin: nodeOperator.admin, name: nodeOperator.name}); + ++s_nodeOperatorId; + emit NodeOperatorAdded(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 + function getNodeOperator(uint256 nodeOperatorId) external view returns (NodeOperator memory) { + return s_nodeOperators[nodeOperatorId]; + } + function addCapability(Capability calldata capability) external onlyOwner { bytes32 capabilityId = getCapabilityID(capability.capabilityType, capability.version); s_capabilities[capabilityId] = capability; @@ -34,7 +82,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { } /// @notice This functions returns a Capability ID packed into a bytes32 for cheaper access - /// @return A unique identifier for the capability + /// @return bytes32 A unique identifier for the capability function getCapabilityID(bytes32 capabilityType, bytes32 version) public pure returns (bytes32) { return keccak256(abi.encodePacked(capabilityType, version)); } diff --git a/contracts/src/v0.8/keystone/test/BaseTest.t.sol b/contracts/src/v0.8/keystone/test/BaseTest.t.sol new file mode 100644 index 00000000000..5c4b4c91809 --- /dev/null +++ b/contracts/src/v0.8/keystone/test/BaseTest.t.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {Test} from "forge-std/Test.sol"; +import {Constants} from "./Constants.t.sol"; +import {CapabilityRegistry} from "../CapabilityRegistry.sol"; + +contract BaseTest is Test, Constants { + CapabilityRegistry internal s_capabilityRegistry; + + function setUp() public virtual { + vm.startPrank(ADMIN); + s_capabilityRegistry = new CapabilityRegistry(); + } + + function _getNodeOperators() internal view returns (CapabilityRegistry.NodeOperator[] memory) { + CapabilityRegistry.NodeOperator[] memory nodeOperators = new CapabilityRegistry.NodeOperator[](2); + nodeOperators[0] = CapabilityRegistry.NodeOperator({admin: NODE_OPERATOR_ONE_ADMIN, name: NODE_OPERATOR_ONE_NAME}); + nodeOperators[1] = CapabilityRegistry.NodeOperator({admin: NODE_OPERATOR_TWO_ADMIN, name: NODE_OPERATOR_TWO_NAME}); + return nodeOperators; + } +} diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry.t.sol deleted file mode 100644 index f5d539d8e34..00000000000 --- a/contracts/src/v0.8/keystone/test/CapabilityRegistry.t.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {Test} from "forge-std/Test.sol"; -import {Capability, CapabilityRegistry} from "../CapabilityRegistry.sol"; - -contract CapabilityRegistryTest is Test { - function setUp() public virtual {} - - function testAddCapability() public { - CapabilityRegistry capabilityRegistry = new CapabilityRegistry(); - - capabilityRegistry.addCapability(Capability("data-streams-reports", "1.0.0")); - - bytes32 capabilityId = capabilityRegistry.getCapabilityID(bytes32("data-streams-reports"), bytes32("1.0.0")); - Capability memory capability = capabilityRegistry.getCapability(capabilityId); - - assertEq(capability.capabilityType, "data-streams-reports"); - assertEq(capability.version, "1.0.0"); - } -} diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol new file mode 100644 index 00000000000..6fbdc43a2c7 --- /dev/null +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddCapabilityTest.t.sol @@ -0,0 +1,17 @@ +// 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 { + function test_AddCapability() public { + s_capabilityRegistry.addCapability(CapabilityRegistry.Capability("data-streams-reports", "1.0.0")); + + bytes32 capabilityId = s_capabilityRegistry.getCapabilityID(bytes32("data-streams-reports"), bytes32("1.0.0")); + CapabilityRegistry.Capability memory capability = s_capabilityRegistry.getCapability(capabilityId); + + assertEq(capability.capabilityType, "data-streams-reports"); + assertEq(capability.version, "1.0.0"); + } +} diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodeOperatorsTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodeOperatorsTest.t.sol new file mode 100644 index 00000000000..388c3ca9cdd --- /dev/null +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry_AddNodeOperatorsTest.t.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilityRegistry} from "../CapabilityRegistry.sol"; + +contract CapabilityRegistry_AddNodeOperatorsTest is BaseTest { + event NodeOperatorAdded(uint256 nodeOperatorId, address indexed admin, string name); + + function test_RevertWhen_CalledByNonAdmin() public { + changePrank(STRANGER); + vm.expectRevert("Only callable by owner"); + s_capabilityRegistry.addNodeOperators(_getNodeOperators()); + } + + function test_RevertWhen_NodeOperatorAdminAddressZero() public { + changePrank(ADMIN); + CapabilityRegistry.NodeOperator[] memory nodeOperators = _getNodeOperators(); + nodeOperators[0].admin = address(0); + vm.expectRevert(CapabilityRegistry.InvalidNodeOperatorAdmin.selector); + s_capabilityRegistry.addNodeOperators(nodeOperators); + } + + function test_AddNodeOperators() public { + changePrank(ADMIN); + + vm.expectEmit(true, true, true, true, address(s_capabilityRegistry)); + emit NodeOperatorAdded(0, NODE_OPERATOR_ONE_ADMIN, NODE_OPERATOR_ONE_NAME); + vm.expectEmit(true, true, true, true, address(s_capabilityRegistry)); + emit NodeOperatorAdded(1, NODE_OPERATOR_TWO_ADMIN, NODE_OPERATOR_TWO_NAME); + s_capabilityRegistry.addNodeOperators(_getNodeOperators()); + + CapabilityRegistry.NodeOperator memory nodeOperatorOne = s_capabilityRegistry.getNodeOperator(0); + assertEq(nodeOperatorOne.admin, NODE_OPERATOR_ONE_ADMIN); + assertEq(nodeOperatorOne.name, NODE_OPERATOR_ONE_NAME); + + CapabilityRegistry.NodeOperator memory nodeOperatorTwo = s_capabilityRegistry.getNodeOperator(1); + assertEq(nodeOperatorTwo.admin, NODE_OPERATOR_TWO_ADMIN); + assertEq(nodeOperatorTwo.name, NODE_OPERATOR_TWO_NAME); + } +} diff --git a/contracts/src/v0.8/keystone/test/Constants.t.sol b/contracts/src/v0.8/keystone/test/Constants.t.sol new file mode 100644 index 00000000000..b7eb85debb1 --- /dev/null +++ b/contracts/src/v0.8/keystone/test/Constants.t.sol @@ -0,0 +1,13 @@ +// 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); + address internal NODE_OPERATOR_ONE_ADMIN = address(3); + string internal NODE_OPERATOR_ONE_NAME = "node-operator-one"; + address internal NODE_OPERATOR_TWO_ADMIN = address(4); + string internal NODE_OPERATOR_TWO_NAME = "node-operator-two"; +} 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 45ae103ac56..ef8b252b924 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 @@ -30,14 +30,19 @@ var ( _ = abi.ConvertType ) -type Capability struct { +type CapabilityRegistryCapability struct { CapabilityType [32]byte Version [32]byte } +type CapabilityRegistryNodeOperator struct { + Admin common.Address + Name string +} + var CapabilityRegistryMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"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\":\"structCapability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"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\":\"structCapability\",\"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\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"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: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6105e5806101576000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c806379ba50971161005b57806379ba5097146101275780638da5cb5b1461012f5780639cb7c5f414610157578063f2fde38b146101be57600080fd5b8063181f5a7714610082578063229111f5146100ca5780636e5f286914610112575b600080fd5b604080518082018252601881527f4361706162696c697479526567697374727920312e302e300000000000000000602082015290516100c191906104dc565b60405180910390f35b6101046100d8366004610548565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b6040519081526020016100c1565b61012561012036600461056a565b6101d1565b005b61012561024e565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100c1565b6101a3610165366004610582565b604080518082019091526000808252602082015250600090815260026020908152604091829020825180840190935280548352600101549082015290565b604080518251815260209283015192810192909252016100c1565b6101256101cc36600461059b565b610350565b6101d9610364565b60408051823560208083018290528085013583850181905284518085038601815260609094018086528451948301949094206000818152600290935294822092835560019092019190915582917f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff069190a25050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146102d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610358610364565b610361816103e7565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146103e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016102cb565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610466576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016102cb565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208083528351808285015260005b81811015610509578581018301518582016040015282016104ed565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6000806040838503121561055b57600080fd5b50508035926020909101359150565b60006040828403121561057c57600080fd5b50919050565b60006020828403121561059457600080fd5b5035919050565b6000602082840312156105ad57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146105d157600080fd5b939250505056fea164736f6c6343000813000a", + 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\":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\":\"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: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b610d9e806101576000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c80636e5f2869116100765780638da5cb5b1161005b5780638da5cb5b146101885780639cb7c5f4146101b0578063f2fde38b1461021757600080fd5b80636e5f28691461016d57806379ba50971461018057600080fd5b8063181f5a77146100a8578063229111f5146100f0578063398f37731461013857806365c14dc71461014d575b600080fd5b604080518082018252601881527f4361706162696c697479526567697374727920312e302e300000000000000000602082015290516100e7919061081d565b60405180910390f35b61012a6100fe366004610837565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b6040519081526020016100e7565b61014b610146366004610859565b61022a565b005b61016061015b3660046108ce565b6103c8565b6040516100e791906108e7565b61014b61017b36600461092a565b6104ae565b61014b61052b565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e7565b6101fc6101be3660046108ce565b604080518082019091526000808252602082015250600090815260026020908152604091829020825180840190935280548352600101549082015290565b604080518251815260209283015192810192909252016100e7565b61014b61022536600461096b565b61062d565b610232610641565b60005b818110156103c357600083838381811061025157610251610986565b905060200281019061026391906109b5565b61026c90610a9a565b805190915073ffffffffffffffffffffffffffffffffffffffff166102bd576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600454604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815260008681526003909252939020825181547fffffffffffffffffffffffff0000000000000000000000000000000000000000169216919091178155915190919060018201906103409082610bff565b5090505060046000815461035390610d19565b909155508151602083015160405173ffffffffffffffffffffffffffffffffffffffff909216917fda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b916103a891859190610d78565b60405180910390a25050806103bc90610d19565b9050610235565b505050565b6040805180820190915260008152606060208201526000828152600360209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff168352600181018054919284019161042590610b64565b80601f016020809104026020016040519081016040528092919081815260200182805461045190610b64565b801561049e5780601f106104735761010080835404028352916020019161049e565b820191906000526020600020905b81548152906001019060200180831161048157829003601f168201915b5050505050815250509050919050565b6104b6610641565b60408051823560208083018290528085013583850181905284518085038601815260609094018086528451948301949094206000818152600290935294822092835560019092019190915582917f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff069190a25050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146105b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610635610641565b61063e816106c4565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016105a8565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610743576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016105a8565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000815180845260005b818110156107df576020818501810151868301820152016107c3565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061083060208301846107b9565b9392505050565b6000806040838503121561084a57600080fd5b50508035926020909101359150565b6000806020838503121561086c57600080fd5b823567ffffffffffffffff8082111561088457600080fd5b818501915085601f83011261089857600080fd5b8135818111156108a757600080fd5b8660208260051b85010111156108bc57600080fd5b60209290920196919550909350505050565b6000602082840312156108e057600080fd5b5035919050565b6020815273ffffffffffffffffffffffffffffffffffffffff82511660208201526000602083015160408084015261092260608401826107b9565b949350505050565b60006040828403121561093c57600080fd5b50919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461096657600080fd5b919050565b60006020828403121561097d57600080fd5b61083082610942565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126109e957600080fd5b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610a4557610a456109f3565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610a9257610a926109f3565b604052919050565b600060408236031215610aac57600080fd5b610ab4610a22565b610abd83610942565b815260208084013567ffffffffffffffff80821115610adb57600080fd5b9085019036601f830112610aee57600080fd5b813581811115610b0057610b006109f3565b610b30847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610a4b565b91508082523684828501011115610b4657600080fd5b80848401858401376000908201840152918301919091525092915050565b600181811c90821680610b7857607f821691505b60208210810361093c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b601f8211156103c357600081815260208120601f850160051c81016020861015610bd85750805b601f850160051c820191505b81811015610bf757828155600101610be4565b505050505050565b815167ffffffffffffffff811115610c1957610c196109f3565b610c2d81610c278454610b64565b84610bb1565b602080601f831160018114610c805760008415610c4a5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610bf7565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015610ccd57888601518255948401946001909101908401610cae565b5085821015610d0957878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610d71577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b82815260406020820152600061092260408301846107b956fea164736f6c6343000813000a", } var CapabilityRegistryABI = CapabilityRegistryMetaData.ABI @@ -176,25 +181,25 @@ func (_CapabilityRegistry *CapabilityRegistryTransactorRaw) Transact(opts *bind. return _CapabilityRegistry.Contract.contract.Transact(opts, method, params...) } -func (_CapabilityRegistry *CapabilityRegistryCaller) GetCapability(opts *bind.CallOpts, capabilityID [32]byte) (Capability, error) { +func (_CapabilityRegistry *CapabilityRegistryCaller) GetCapability(opts *bind.CallOpts, capabilityID [32]byte) (CapabilityRegistryCapability, error) { var out []interface{} err := _CapabilityRegistry.contract.Call(opts, &out, "getCapability", capabilityID) if err != nil { - return *new(Capability), err + return *new(CapabilityRegistryCapability), err } - out0 := *abi.ConvertType(out[0], new(Capability)).(*Capability) + out0 := *abi.ConvertType(out[0], new(CapabilityRegistryCapability)).(*CapabilityRegistryCapability) return out0, err } -func (_CapabilityRegistry *CapabilityRegistrySession) GetCapability(capabilityID [32]byte) (Capability, error) { +func (_CapabilityRegistry *CapabilityRegistrySession) GetCapability(capabilityID [32]byte) (CapabilityRegistryCapability, error) { return _CapabilityRegistry.Contract.GetCapability(&_CapabilityRegistry.CallOpts, capabilityID) } -func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapability(capabilityID [32]byte) (Capability, error) { +func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapability(capabilityID [32]byte) (CapabilityRegistryCapability, error) { return _CapabilityRegistry.Contract.GetCapability(&_CapabilityRegistry.CallOpts, capabilityID) } @@ -220,6 +225,28 @@ func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapabilityID(capa return _CapabilityRegistry.Contract.GetCapabilityID(&_CapabilityRegistry.CallOpts, capabilityType, version) } +func (_CapabilityRegistry *CapabilityRegistryCaller) GetNodeOperator(opts *bind.CallOpts, nodeOperatorId *big.Int) (CapabilityRegistryNodeOperator, error) { + var out []interface{} + err := _CapabilityRegistry.contract.Call(opts, &out, "getNodeOperator", nodeOperatorId) + + if err != nil { + return *new(CapabilityRegistryNodeOperator), err + } + + out0 := *abi.ConvertType(out[0], new(CapabilityRegistryNodeOperator)).(*CapabilityRegistryNodeOperator) + + return out0, err + +} + +func (_CapabilityRegistry *CapabilityRegistrySession) GetNodeOperator(nodeOperatorId *big.Int) (CapabilityRegistryNodeOperator, error) { + return _CapabilityRegistry.Contract.GetNodeOperator(&_CapabilityRegistry.CallOpts, nodeOperatorId) +} + +func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetNodeOperator(nodeOperatorId *big.Int) (CapabilityRegistryNodeOperator, error) { + return _CapabilityRegistry.Contract.GetNodeOperator(&_CapabilityRegistry.CallOpts, nodeOperatorId) +} + func (_CapabilityRegistry *CapabilityRegistryCaller) Owner(opts *bind.CallOpts) (common.Address, error) { var out []interface{} err := _CapabilityRegistry.contract.Call(opts, &out, "owner") @@ -276,18 +303,30 @@ func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AcceptOwnership( return _CapabilityRegistry.Contract.AcceptOwnership(&_CapabilityRegistry.TransactOpts) } -func (_CapabilityRegistry *CapabilityRegistryTransactor) AddCapability(opts *bind.TransactOpts, capability Capability) (*types.Transaction, error) { +func (_CapabilityRegistry *CapabilityRegistryTransactor) AddCapability(opts *bind.TransactOpts, capability CapabilityRegistryCapability) (*types.Transaction, error) { return _CapabilityRegistry.contract.Transact(opts, "addCapability", capability) } -func (_CapabilityRegistry *CapabilityRegistrySession) AddCapability(capability Capability) (*types.Transaction, error) { +func (_CapabilityRegistry *CapabilityRegistrySession) AddCapability(capability CapabilityRegistryCapability) (*types.Transaction, error) { return _CapabilityRegistry.Contract.AddCapability(&_CapabilityRegistry.TransactOpts, capability) } -func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AddCapability(capability Capability) (*types.Transaction, error) { +func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AddCapability(capability CapabilityRegistryCapability) (*types.Transaction, error) { return _CapabilityRegistry.Contract.AddCapability(&_CapabilityRegistry.TransactOpts, capability) } +func (_CapabilityRegistry *CapabilityRegistryTransactor) AddNodeOperators(opts *bind.TransactOpts, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) { + return _CapabilityRegistry.contract.Transact(opts, "addNodeOperators", nodeOperators) +} + +func (_CapabilityRegistry *CapabilityRegistrySession) AddNodeOperators(nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.AddNodeOperators(&_CapabilityRegistry.TransactOpts, nodeOperators) +} + +func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AddNodeOperators(nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.AddNodeOperators(&_CapabilityRegistry.TransactOpts, nodeOperators) +} + func (_CapabilityRegistry *CapabilityRegistryTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { return _CapabilityRegistry.contract.Transact(opts, "transferOwnership", to) } @@ -427,6 +466,135 @@ func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseCapabilityAdded(log return event, nil } +type CapabilityRegistryNodeOperatorAddedIterator struct { + Event *CapabilityRegistryNodeOperatorAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilityRegistryNodeOperatorAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryNodeOperatorAdded) + 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(CapabilityRegistryNodeOperatorAdded) + 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 *CapabilityRegistryNodeOperatorAddedIterator) Error() error { + return it.fail +} + +func (it *CapabilityRegistryNodeOperatorAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilityRegistryNodeOperatorAdded struct { + NodeOperatorId *big.Int + Admin common.Address + Name string + Raw types.Log +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterNodeOperatorAdded(opts *bind.FilterOpts, admin []common.Address) (*CapabilityRegistryNodeOperatorAddedIterator, error) { + + var adminRule []interface{} + for _, adminItem := range admin { + adminRule = append(adminRule, adminItem) + } + + logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "NodeOperatorAdded", adminRule) + if err != nil { + return nil, err + } + return &CapabilityRegistryNodeOperatorAddedIterator{contract: _CapabilityRegistry.contract, event: "NodeOperatorAdded", logs: logs, sub: sub}, nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchNodeOperatorAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeOperatorAdded, admin []common.Address) (event.Subscription, error) { + + var adminRule []interface{} + for _, adminItem := range admin { + adminRule = append(adminRule, adminItem) + } + + logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "NodeOperatorAdded", 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(CapabilityRegistryNodeOperatorAdded) + if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeOperatorAdded", 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) ParseNodeOperatorAdded(log types.Log) (*CapabilityRegistryNodeOperatorAdded, error) { + event := new(CapabilityRegistryNodeOperatorAdded) + if err := _CapabilityRegistry.contract.UnpackLog(event, "NodeOperatorAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type CapabilityRegistryOwnershipTransferRequestedIterator struct { Event *CapabilityRegistryOwnershipTransferRequested @@ -703,6 +871,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["NodeOperatorAdded"].ID: + return _CapabilityRegistry.ParseNodeOperatorAdded(log) case _CapabilityRegistry.abi.Events["OwnershipTransferRequested"].ID: return _CapabilityRegistry.ParseOwnershipTransferRequested(log) case _CapabilityRegistry.abi.Events["OwnershipTransferred"].ID: @@ -717,6 +887,10 @@ func (CapabilityRegistryCapabilityAdded) Topic() common.Hash { return common.HexToHash("0x65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff06") } +func (CapabilityRegistryNodeOperatorAdded) Topic() common.Hash { + return common.HexToHash("0xda6697b182650034bd205cdc2dbfabb06bdb3a0a83a2b45bfefa3c4881284e0b") +} + func (CapabilityRegistryOwnershipTransferRequested) Topic() common.Hash { return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") } @@ -730,17 +904,21 @@ func (_CapabilityRegistry *CapabilityRegistry) Address() common.Address { } type CapabilityRegistryInterface interface { - GetCapability(opts *bind.CallOpts, capabilityID [32]byte) (Capability, error) + GetCapability(opts *bind.CallOpts, capabilityID [32]byte) (CapabilityRegistryCapability, error) GetCapabilityID(opts *bind.CallOpts, capabilityType [32]byte, version [32]byte) ([32]byte, error) + GetNodeOperator(opts *bind.CallOpts, nodeOperatorId *big.Int) (CapabilityRegistryNodeOperator, error) + Owner(opts *bind.CallOpts) (common.Address, error) TypeAndVersion(opts *bind.CallOpts) (string, error) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - AddCapability(opts *bind.TransactOpts, capability Capability) (*types.Transaction, error) + AddCapability(opts *bind.TransactOpts, capability CapabilityRegistryCapability) (*types.Transaction, error) + + AddNodeOperators(opts *bind.TransactOpts, nodeOperators []CapabilityRegistryNodeOperator) (*types.Transaction, error) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) @@ -750,6 +928,12 @@ type CapabilityRegistryInterface interface { ParseCapabilityAdded(log types.Log) (*CapabilityRegistryCapabilityAdded, error) + FilterNodeOperatorAdded(opts *bind.FilterOpts, admin []common.Address) (*CapabilityRegistryNodeOperatorAddedIterator, error) + + WatchNodeOperatorAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryNodeOperatorAdded, admin []common.Address) (event.Subscription, error) + + ParseNodeOperatorAdded(log types.Log) (*CapabilityRegistryNodeOperatorAdded, 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 98fd35e188b..836eb3e68b7 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 fbaf8eceb929494bdfe0028921a0742da525cb4ec1b6d57a1382eda46fa32c64 +keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin 579334dfcb59da4221823735dc815116745b488ddde327199367e04457aac808 ocr3_capability: ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.bin 9dcbdf55bd5729ba266148da3f17733eb592c871c2108ccca546618628fd9ad2