From 9e5003813a6716ce67a6a6af5bf87d1df0397527 Mon Sep 17 00:00:00 2001 From: Borja Aranda Date: Mon, 16 Dec 2024 18:54:17 +0100 Subject: [PATCH 1/8] feat: XMTP messages contracts are upgradeable and pausable --- contracts/.gitignore | 2 + contracts/foundry.toml | 6 +++ contracts/remappings.txt | 5 ++- contracts/script/DeployerGroupMessages.s.sol | 28 ++++++++++++ ...loyer.s.sol => DeployerNodeRegistry.s.sol} | 2 +- contracts/soldeer.lock | 7 +++ contracts/src/GroupMessages.sol | 45 +++++++++++++++++-- contracts/src/IdentityUpdates.sol | 45 +++++++++++++++++-- contracts/src/Nodes.sol | 4 +- contracts/test/GroupMessage.t.sol | 2 +- contracts/test/IdentityUpdates.t.sol | 2 +- contracts/test/Nodes.sol | 4 +- 12 files changed, 135 insertions(+), 17 deletions(-) create mode 100644 contracts/script/DeployerGroupMessages.s.sol rename contracts/script/{Deployer.s.sol => DeployerNodeRegistry.s.sol} (80%) diff --git a/contracts/.gitignore b/contracts/.gitignore index ebe566f2..704b55a4 100644 --- a/contracts/.gitignore +++ b/contracts/.gitignore @@ -4,6 +4,8 @@ out/ # Ignores development broadcast logs !/broadcast +/broadcast/*/11155111/ +/broadcast/*/241320161/ /broadcast/*/31337/ /broadcast/**/dry-run/ diff --git a/contracts/foundry.toml b/contracts/foundry.toml index 66cb3155..acf06f0e 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -7,10 +7,16 @@ libs = ["dependencies"] gas_reports = ["*"] optimizer = true optimizer_runs = 10_000 +remappings = [ + "@openzeppelin/contracts/=dependencies/@openzeppelin-contracts-5.1.0/", + "@openzeppelin-contracts-upgradeable/=dependencies/@openzeppelin-contracts-upgradeable-5.1.0/", + "forge-std/=dependencies/forge-std-1.9.4/", +] [soldeer] recursive_deps = true [dependencies] forge-std = "1.9.4" +"@openzeppelin-contracts-upgradeable" = "5.1.0" "@openzeppelin-contracts" = "5.1.0" diff --git a/contracts/remappings.txt b/contracts/remappings.txt index 8b4a64d6..a1aecfd1 100644 --- a/contracts/remappings.txt +++ b/contracts/remappings.txt @@ -1,2 +1,3 @@ -@openzeppelin-contracts-5.1.0/=dependencies/@openzeppelin-contracts-5.1.0/ -forge-std-1.9.4/=dependencies/forge-std-1.9.4/ +@openzeppelin/contracts/=dependencies/@openzeppelin-contracts-5.1.0/ +@openzeppelin-contracts-upgradeable/=dependencies/@openzeppelin-contracts-upgradeable-5.1.0/ +forge-std/=dependencies/forge-std-1.9.4/ diff --git a/contracts/script/DeployerGroupMessages.s.sol b/contracts/script/DeployerGroupMessages.s.sol new file mode 100644 index 00000000..8799afaa --- /dev/null +++ b/contracts/script/DeployerGroupMessages.s.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.28; + +import "forge-std/src/Script.sol"; +import "src/GroupMessages.sol"; +import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; + +contract DeployProxiedGroupMessages is Script { + function run() external { + uint256 privateKey = vm.envUint("PRIVATE_KEY"); + vm.startBroadcast(privateKey); + + // Step 1: Deploy the implementation contract + GroupMessages groupMessagesImpl = new GroupMessages(); + + // Step 2: Deploy the proxy contract + ERC1967Proxy proxy = new ERC1967Proxy( + address(groupMessagesImpl), + abi.encodeWithSelector(GroupMessages.initialize.selector) + ); + + // Log the deployed contract addresses + console.log("Implementation Address:", address(groupMessagesImpl)); + console.log("Proxy Address:", address(proxy)); + + vm.stopBroadcast(); + } +} diff --git a/contracts/script/Deployer.s.sol b/contracts/script/DeployerNodeRegistry.s.sol similarity index 80% rename from contracts/script/Deployer.s.sol rename to contracts/script/DeployerNodeRegistry.s.sol index e16949d3..361ab3db 100644 --- a/contracts/script/Deployer.s.sol +++ b/contracts/script/DeployerNodeRegistry.s.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.28; -import {Script, console} from "forge-std-1.9.4/src/Script.sol"; +import {Script, console} from "forge-std/src/Script.sol"; import "../src/Nodes.sol"; contract Deployer is Script { diff --git a/contracts/soldeer.lock b/contracts/soldeer.lock index ecca7c99..7c7c4295 100644 --- a/contracts/soldeer.lock +++ b/contracts/soldeer.lock @@ -5,6 +5,13 @@ url = "https://soldeer-revisions.s3.amazonaws.com/@openzeppelin-contracts/5_1_0_ checksum = "fd3d1ea561cb27897008aee18ada6e85f248eb161c86e4435272fc2b5777574f" integrity = "cb6cf6e878f2943b2291d5636a9d72ac51d43d8135896ceb6cf88d36c386f212" +[[dependencies]] +name = "@openzeppelin-contracts-upgradeable" +version = "5.1.0" +url = "https://soldeer-revisions.s3.amazonaws.com/@openzeppelin-contracts-upgradeable/5_1_0_19-10-2024_10:28:58_contracts-upgradeable.zip" +checksum = "87854223d14941d6fda3d78d900217e79e25755ea5bc48beca035766fa6a4e7e" +integrity = "826fb621339dcee4261f848b283ec86364743d3c289d61f621747d95e315215a" + [[dependencies]] name = "forge-std" version = "1.9.4" diff --git a/contracts/src/GroupMessages.sol b/contracts/src/GroupMessages.sol index 39b40c16..015d3017 100644 --- a/contracts/src/GroupMessages.sol +++ b/contracts/src/GroupMessages.sol @@ -1,14 +1,51 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.28; -contract GroupMessages { +import "@openzeppelin-contracts-upgradeable/access/AccessControlUpgradeable.sol"; +import "@openzeppelin-contracts-upgradeable/proxy/utils/Initializable.sol"; +import "@openzeppelin-contracts-upgradeable/utils/PausableUpgradeable.sol"; +import "@openzeppelin-contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; + +/// @title XMTP Group Messages Contract +contract GroupMessages is Initializable, AccessControlUpgradeable, UUPSUpgradeable, PausableUpgradeable { event MessageSent(bytes32 groupId, bytes message, uint64 sequenceId); + event UpgradeAuthorized(address deployer, address newImplementation); - uint64 sequenceId; + uint64 private sequenceId; - function addMessage(bytes32 groupId, bytes memory message) public { - sequenceId++; + /// @notice Initializes the contract with the deployer as admin. + function initialize() public initializer { + __UUPSUpgradeable_init(); + __AccessControl_init(); + __Pausable_init(); + _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); + } + + /// @notice Pauses the contract. + function pause() public onlyRole(DEFAULT_ADMIN_ROLE) { + _pause(); + } + + /// @notice Unpauses the contract. + function unpause() public onlyRole(DEFAULT_ADMIN_ROLE) { + _unpause(); + } + + /// @notice Adds a message to the group. + /// @param groupId The group ID. + /// @param message The message in bytes. + function addMessage(bytes32 groupId, bytes calldata message) public whenNotPaused { + /// @dev Incrementing the sequence ID is safe here due to the extremely large limit of uint64. + unchecked { + sequenceId++; + } emit MessageSent(groupId, message, sequenceId); } + + /// @dev Authorizes the upgrade of the contract. + /// @param newImplementation The address of the new implementation. + function _authorizeUpgrade(address newImplementation) internal override onlyRole(DEFAULT_ADMIN_ROLE) { + emit UpgradeAuthorized(msg.sender, newImplementation); + } } diff --git a/contracts/src/IdentityUpdates.sol b/contracts/src/IdentityUpdates.sol index 02017a32..4eac7aa9 100644 --- a/contracts/src/IdentityUpdates.sol +++ b/contracts/src/IdentityUpdates.sol @@ -1,14 +1,51 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.28; -contract IdentityUpdates { +import "@openzeppelin-contracts-upgradeable/access/AccessControlUpgradeable.sol"; +import "@openzeppelin-contracts-upgradeable/proxy/utils/Initializable.sol"; +import "@openzeppelin-contracts-upgradeable/utils/PausableUpgradeable.sol"; +import "@openzeppelin-contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; + +/// @title XMTP Identity Updates Contract +contract IdentityUpdates is Initializable, AccessControlUpgradeable, UUPSUpgradeable, PausableUpgradeable { event IdentityUpdateCreated(bytes32 inboxId, bytes update, uint64 sequenceId); + event UpgradeAuthorized(address deployer, address newImplementation); - uint64 sequenceId; + uint64 private sequenceId; - function addIdentityUpdate(bytes32 inboxId, bytes memory update) public { - sequenceId++; + /// @notice Initializes the contract with the deployer as admin. + function initialize() public initializer { + __UUPSUpgradeable_init(); + __AccessControl_init(); + __Pausable_init(); + _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); + } + + /// @notice Pauses the contract. + function pause() public onlyRole(DEFAULT_ADMIN_ROLE) { + _pause(); + } + + /// @notice Unpauses the contract. + function unpause() public onlyRole(DEFAULT_ADMIN_ROLE) { + _unpause(); + } + + /// @notice Adds an identity update to an specific inbox ID. + /// @param inboxId The inbox ID. + /// @param update The identity update in bytes. + function addIdentityUpdate(bytes32 inboxId, bytes calldata update) public whenNotPaused { + /// @dev Incrementing the sequence ID is safe here due to the extremely large limit of uint64. + unchecked { + sequenceId++; + } emit IdentityUpdateCreated(inboxId, update, sequenceId); } + + /// @dev Authorizes the upgrade of the contract. + /// @param newImplementation The address of the new implementation. + function _authorizeUpgrade(address newImplementation) internal override onlyRole(DEFAULT_ADMIN_ROLE) { + emit UpgradeAuthorized(msg.sender, newImplementation); + } } diff --git a/contracts/src/Nodes.sol b/contracts/src/Nodes.sol index b7d2d0fb..bcea51a7 100644 --- a/contracts/src/Nodes.sol +++ b/contracts/src/Nodes.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.28; -import "@openzeppelin-contracts-5.1.0/token/ERC721/ERC721.sol"; -import "@openzeppelin-contracts-5.1.0/access/Ownable.sol"; +import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; /** * A NFT contract for XMTP Node Operators. diff --git a/contracts/test/GroupMessage.t.sol b/contracts/test/GroupMessage.t.sol index e1f761cd..4e5ce2f4 100644 --- a/contracts/test/GroupMessage.t.sol +++ b/contracts/test/GroupMessage.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.28; -import {Test, console} from "forge-std-1.9.4/src/Test.sol"; +import {Test, console} from "forge-std/src/Test.sol"; import {GroupMessages} from "../src/GroupMessages.sol"; contract GroupMessagesTest is Test { diff --git a/contracts/test/IdentityUpdates.t.sol b/contracts/test/IdentityUpdates.t.sol index a4d17fa8..f46e1e3e 100644 --- a/contracts/test/IdentityUpdates.t.sol +++ b/contracts/test/IdentityUpdates.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.28; -import {Test, console} from "forge-std-1.9.4/src/Test.sol"; +import {Test, console} from "forge-std/src/Test.sol"; import {IdentityUpdates} from "../src/IdentityUpdates.sol"; contract IdentityUpdatesTest is Test { diff --git a/contracts/test/Nodes.sol b/contracts/test/Nodes.sol index df4b21a5..0c9e7015 100644 --- a/contracts/test/Nodes.sol +++ b/contracts/test/Nodes.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.28; -import {Test, console} from "forge-std-1.9.4/src/Test.sol"; -import {Ownable} from "@openzeppelin-contracts-5.1.0/access/Ownable.sol"; +import {Test, console} from "forge-std/src/Test.sol"; +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {Nodes} from "../src/Nodes.sol"; contract NodesTest is Test { From 1e9953da2da5710ec9566b19717eb814d39e176e Mon Sep 17 00:00:00 2001 From: Borja Aranda Date: Wed, 18 Dec 2024 19:19:26 +0100 Subject: [PATCH 2/8] feat: add tests and scripts --- contracts/remappings.txt | 2 +- contracts/script/DeployGroupMessages.s.sol | 34 +++++ contracts/script/DeployIdentityUpdates.s.sol | 34 +++++ ...egistry.s.sol => DeployNodeRegistry.s.sol} | 2 +- contracts/script/DeployerGroupMessages.s.sol | 28 ---- .../upgrades/UpgradeGroupMessages.s.sol | 36 +++++ .../upgrades/UpgradeIdentityUpdates.s.sol | 36 +++++ contracts/src/GroupMessages.sol | 15 +- contracts/src/IdentityUpdates.sol | 15 +- contracts/test/GroupMessage.t.sol | 129 +++++++++++++++++- contracts/test/IdentityUpdates.t.sol | 124 ++++++++++++++++- 11 files changed, 408 insertions(+), 47 deletions(-) create mode 100644 contracts/script/DeployGroupMessages.s.sol create mode 100644 contracts/script/DeployIdentityUpdates.s.sol rename contracts/script/{DeployerNodeRegistry.s.sol => DeployNodeRegistry.s.sol} (91%) delete mode 100644 contracts/script/DeployerGroupMessages.s.sol create mode 100644 contracts/script/upgrades/UpgradeGroupMessages.s.sol create mode 100644 contracts/script/upgrades/UpgradeIdentityUpdates.s.sol diff --git a/contracts/remappings.txt b/contracts/remappings.txt index a1aecfd1..1232be47 100644 --- a/contracts/remappings.txt +++ b/contracts/remappings.txt @@ -1,3 +1,3 @@ -@openzeppelin/contracts/=dependencies/@openzeppelin-contracts-5.1.0/ @openzeppelin-contracts-upgradeable/=dependencies/@openzeppelin-contracts-upgradeable-5.1.0/ +@openzeppelin/contracts/=dependencies/@openzeppelin-contracts-5.1.0/ forge-std/=dependencies/forge-std-1.9.4/ diff --git a/contracts/script/DeployGroupMessages.s.sol b/contracts/script/DeployGroupMessages.s.sol new file mode 100644 index 00000000..8b49702e --- /dev/null +++ b/contracts/script/DeployGroupMessages.s.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.28; + +import "forge-std/src/Script.sol"; +import "forge-std/src/Vm.sol"; +import "src/GroupMessages.sol"; +import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; + +contract DeployGroupMessages is Script { + function run() external { + uint256 privateKey = vm.envUint("PRIVATE_KEY"); + address deployer = vm.addr(privateKey); + vm.startBroadcast(privateKey); + + // Step 1: Deploy the implementation contract. + GroupMessages groupMessagesImpl = new GroupMessages(); + + // Step 2: Deploy the proxy contract. + ERC1967Proxy proxy = + new ERC1967Proxy( + address(groupMessagesImpl), + abi.encodeWithSelector(GroupMessages.initialize.selector, deployer) + ); + + console.log( + '{"deployer":"%s","proxy":"%s","implementation":"%s"}', + deployer, + address(proxy), + address(groupMessagesImpl) + ); + + vm.stopBroadcast(); + } +} diff --git a/contracts/script/DeployIdentityUpdates.s.sol b/contracts/script/DeployIdentityUpdates.s.sol new file mode 100644 index 00000000..cf969b33 --- /dev/null +++ b/contracts/script/DeployIdentityUpdates.s.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.28; + +import "forge-std/src/Script.sol"; +import "forge-std/src/Vm.sol"; +import "src/IdentityUpdates.sol"; +import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; + +contract DeployIdentityUpdates is Script { + function run() external { + uint256 privateKey = vm.envUint("PRIVATE_KEY"); + address deployer = vm.addr(privateKey); + vm.startBroadcast(privateKey); + + // Step 1: Deploy the implementation contract + IdentityUpdates idUpdatesImpl = new IdentityUpdates(); + + // Step 2: Deploy the proxy contract + ERC1967Proxy proxy = + new ERC1967Proxy( + address(idUpdatesImpl), + abi.encodeWithSelector(IdentityUpdates.initialize.selector, deployer) + ); + + console.log( + '{"deployer":"%s","proxy":"%s","implementation":"%s"}', + deployer, + address(proxy), + address(idUpdatesImpl) + ); + + vm.stopBroadcast(); + } +} diff --git a/contracts/script/DeployerNodeRegistry.s.sol b/contracts/script/DeployNodeRegistry.s.sol similarity index 91% rename from contracts/script/DeployerNodeRegistry.s.sol rename to contracts/script/DeployNodeRegistry.s.sol index 361ab3db..210fdd31 100644 --- a/contracts/script/DeployerNodeRegistry.s.sol +++ b/contracts/script/DeployNodeRegistry.s.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.28; import {Script, console} from "forge-std/src/Script.sol"; -import "../src/Nodes.sol"; +import "src/Nodes.sol"; contract Deployer is Script { function setUp() public {} diff --git a/contracts/script/DeployerGroupMessages.s.sol b/contracts/script/DeployerGroupMessages.s.sol deleted file mode 100644 index 8799afaa..00000000 --- a/contracts/script/DeployerGroupMessages.s.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.28; - -import "forge-std/src/Script.sol"; -import "src/GroupMessages.sol"; -import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; - -contract DeployProxiedGroupMessages is Script { - function run() external { - uint256 privateKey = vm.envUint("PRIVATE_KEY"); - vm.startBroadcast(privateKey); - - // Step 1: Deploy the implementation contract - GroupMessages groupMessagesImpl = new GroupMessages(); - - // Step 2: Deploy the proxy contract - ERC1967Proxy proxy = new ERC1967Proxy( - address(groupMessagesImpl), - abi.encodeWithSelector(GroupMessages.initialize.selector) - ); - - // Log the deployed contract addresses - console.log("Implementation Address:", address(groupMessagesImpl)); - console.log("Proxy Address:", address(proxy)); - - vm.stopBroadcast(); - } -} diff --git a/contracts/script/upgrades/UpgradeGroupMessages.s.sol b/contracts/script/upgrades/UpgradeGroupMessages.s.sol new file mode 100644 index 00000000..38b04c0d --- /dev/null +++ b/contracts/script/upgrades/UpgradeGroupMessages.s.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.28; + +import "forge-std/src/Script.sol"; +import "forge-std/src/Vm.sol"; +import "src/GroupMessages.sol"; +import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; + +contract UpgradeGroupMessages is Script { + function run() external { + address proxyAddress = vm.envAddress("XMTP_GROUP_MESSAGES_PROXY_ADDRESS"); + require(proxyAddress != address(0), "XMTP_GROUP_MESSAGES_PROXY_ADDRESS not set"); + + uint256 privateKey = vm.envUint("PRIVATE_KEY"); + address upgrader = vm.addr(privateKey); + vm.startBroadcast(privateKey); + + // Step 1: Deploy the new implementation contract. + GroupMessages newImplementation = new GroupMessages(); + + // Step 2: Initialize the proxy. + GroupMessages proxy = GroupMessages(proxyAddress); + + // Step 3: Upgrade the proxy pointer to the new implementation. + proxy.upgradeToAndCall(address(newImplementation), ""); + + console.log( + '{"upgrader":"%s","proxy":"%s","newImplementation":"%s"}', + upgrader, + address(proxy), + address(newImplementation) + ); + + vm.stopBroadcast(); + } +} diff --git a/contracts/script/upgrades/UpgradeIdentityUpdates.s.sol b/contracts/script/upgrades/UpgradeIdentityUpdates.s.sol new file mode 100644 index 00000000..4c9d2dd4 --- /dev/null +++ b/contracts/script/upgrades/UpgradeIdentityUpdates.s.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.28; + +import "forge-std/src/Script.sol"; +import "forge-std/src/Vm.sol"; +import "src/IdentityUpdates.sol"; +import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; + +contract UpgradeGroupMessages is Script { + function run() external { + address proxyAddress = vm.envAddress("XMTP_IDENTITY_UPDATES_PROXY_ADDRESS"); + require(proxyAddress != address(0), "XMTP_IDENTITY_UPDATES_PROXY_ADDRESS not set"); + + uint256 privateKey = vm.envUint("PRIVATE_KEY"); + address upgrader = vm.addr(privateKey); + vm.startBroadcast(privateKey); + + // Step 1: Deploy the new implementation contract. + IdentityUpdates newImplementation = new IdentityUpdates(); + + // Step 2: Initialize the proxy. + IdentityUpdates proxy = IdentityUpdates(proxyAddress); + + // Step 3: Upgrade the proxy pointer to the new implementation. + proxy.upgradeToAndCall(address(newImplementation), ""); + + console.log( + '{"upgrader":"%s","proxy":"%s","newImplementation":"%s"}', + upgrader, + address(proxy), + address(newImplementation) + ); + + vm.stopBroadcast(); + } +} diff --git a/contracts/src/GroupMessages.sol b/contracts/src/GroupMessages.sol index 015d3017..20482eeb 100644 --- a/contracts/src/GroupMessages.sol +++ b/contracts/src/GroupMessages.sol @@ -11,14 +11,21 @@ contract GroupMessages is Initializable, AccessControlUpgradeable, UUPSUpgradeab event MessageSent(bytes32 groupId, bytes message, uint64 sequenceId); event UpgradeAuthorized(address deployer, address newImplementation); + error InvalidMessage(); + uint64 private sequenceId; + /// @dev Reserved storage gap for future upgrades + uint256[50] private __gap; + /// @notice Initializes the contract with the deployer as admin. - function initialize() public initializer { + function initialize(address _admin) public initializer { + require(_admin != address(0), "Admin address cannot be zero"); __UUPSUpgradeable_init(); __AccessControl_init(); __Pausable_init(); - _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); + + _grantRole(DEFAULT_ADMIN_ROLE, _admin); } /// @notice Pauses the contract. @@ -35,6 +42,9 @@ contract GroupMessages is Initializable, AccessControlUpgradeable, UUPSUpgradeab /// @param groupId The group ID. /// @param message The message in bytes. function addMessage(bytes32 groupId, bytes calldata message) public whenNotPaused { + /// @dev 78 bytes contains the minimum length of a valid message. + require(message.length >= 78, InvalidMessage()); + /// @dev Incrementing the sequence ID is safe here due to the extremely large limit of uint64. unchecked { sequenceId++; @@ -46,6 +56,7 @@ contract GroupMessages is Initializable, AccessControlUpgradeable, UUPSUpgradeab /// @dev Authorizes the upgrade of the contract. /// @param newImplementation The address of the new implementation. function _authorizeUpgrade(address newImplementation) internal override onlyRole(DEFAULT_ADMIN_ROLE) { + require(newImplementation != address(0), "New implementation cannot be zero address"); emit UpgradeAuthorized(msg.sender, newImplementation); } } diff --git a/contracts/src/IdentityUpdates.sol b/contracts/src/IdentityUpdates.sol index 4eac7aa9..b2bc84ec 100644 --- a/contracts/src/IdentityUpdates.sol +++ b/contracts/src/IdentityUpdates.sol @@ -11,14 +11,21 @@ contract IdentityUpdates is Initializable, AccessControlUpgradeable, UUPSUpgrade event IdentityUpdateCreated(bytes32 inboxId, bytes update, uint64 sequenceId); event UpgradeAuthorized(address deployer, address newImplementation); + error InvalidIdentityUpdate(); + uint64 private sequenceId; + /// @dev Reserved storage gap for future upgrades + uint256[50] private __gap; + /// @notice Initializes the contract with the deployer as admin. - function initialize() public initializer { + function initialize(address _admin) public initializer { + require(_admin != address(0), "Admin address cannot be zero"); __UUPSUpgradeable_init(); __AccessControl_init(); __Pausable_init(); - _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); + + _grantRole(DEFAULT_ADMIN_ROLE, _admin); } /// @notice Pauses the contract. @@ -35,6 +42,9 @@ contract IdentityUpdates is Initializable, AccessControlUpgradeable, UUPSUpgrade /// @param inboxId The inbox ID. /// @param update The identity update in bytes. function addIdentityUpdate(bytes32 inboxId, bytes calldata update) public whenNotPaused { + /// @dev 104 bytes contains the minimum length of a valid IdentityUpdate. + require(update.length >= 104, InvalidIdentityUpdate()); + /// @dev Incrementing the sequence ID is safe here due to the extremely large limit of uint64. unchecked { sequenceId++; @@ -46,6 +56,7 @@ contract IdentityUpdates is Initializable, AccessControlUpgradeable, UUPSUpgrade /// @dev Authorizes the upgrade of the contract. /// @param newImplementation The address of the new implementation. function _authorizeUpgrade(address newImplementation) internal override onlyRole(DEFAULT_ADMIN_ROLE) { + require(newImplementation != address(0), "New implementation cannot be zero address"); emit UpgradeAuthorized(msg.sender, newImplementation); } } diff --git a/contracts/test/GroupMessage.t.sol b/contracts/test/GroupMessage.t.sol index 4e5ce2f4..543fd8cf 100644 --- a/contracts/test/GroupMessage.t.sol +++ b/contracts/test/GroupMessage.t.sol @@ -1,23 +1,138 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.28; +import "forge-std/src/Vm.sol"; import {Test, console} from "forge-std/src/Test.sol"; -import {GroupMessages} from "../src/GroupMessages.sol"; +import {GroupMessages} from "src/GroupMessages.sol"; +import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; +import {Initializable} from "@openzeppelin-contracts-upgradeable/proxy/utils/Initializable.sol"; +import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; contract GroupMessagesTest is Test { - GroupMessages public groupMessages; + bytes32 constant DEFAULT_ADMIN_ROLE = 0x00; + bytes32 constant EIP1967_IMPL_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + bytes32 constant GROUP_ID = 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef; + + GroupMessages groupMessagesImpl; + ERC1967Proxy proxy; + GroupMessages groupMessages; + + address admin = address(this); + address unauthorized = address(0x1); function setUp() public { - groupMessages = new GroupMessages(); + groupMessagesImpl = new GroupMessages(); + + proxy = new ERC1967Proxy( + address(groupMessagesImpl), + abi.encodeWithSelector(GroupMessages.initialize.selector, admin) + ); + + groupMessages = GroupMessages(address(proxy)); } - function test_AddMessage2kb() public { - bytes32 groupId = bytes32(0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef); + function testAddMessageValid() public { bytes memory message = new bytes(1024); for (uint256 i = 0; i < message.length; i++) { message[i] = bytes1(uint8(i % 256)); // Set each byte to its index modulo 256 } - groupMessages.addMessage(groupId, message); + vm.expectEmit(address(groupMessages)); + emit GroupMessages.MessageSent(GROUP_ID, message, 1); + + groupMessages.addMessage(GROUP_ID, message); + } + + function testAddMessageInvalid() public { + bytes memory message = new bytes(77); + for (uint256 i = 0; i < message.length; i++) { + message[i] = bytes1(uint8(i % 256)); + } + + vm.expectRevert(GroupMessages.InvalidMessage.selector); + groupMessages.addMessage(GROUP_ID, message); + } + + function testInvalidReinitialization() public { + vm.expectRevert(Initializable.InvalidInitialization.selector); + groupMessages.initialize(admin); + } + + function testPauseUnpause() public { + groupMessages.pause(); + + vm.prank(unauthorized); + vm.expectRevert(); + groupMessages.unpause(); + + groupMessages.unpause(); + + vm.prank(unauthorized); + vm.expectRevert(); + groupMessages.pause(); + } + + function testRoles() public { + groupMessages.grantRole(DEFAULT_ADMIN_ROLE, unauthorized); + + vm.startPrank(unauthorized); + groupMessages.pause(); + groupMessages.unpause(); + vm.stopPrank(); + + groupMessages.revokeRole(DEFAULT_ADMIN_ROLE, unauthorized); + + vm.prank(unauthorized); + vm.expectRevert(revertRoleData(unauthorized)); + groupMessages.pause(); + + groupMessages.renounceRole(DEFAULT_ADMIN_ROLE, admin); + vm.expectRevert(revertRoleData(admin)); + groupMessages.pause(); + } + + function testUpgradeImplementation() public { + GroupMessages newGroupMessagesImpl = new GroupMessages(); + address newImplAddress = address(newGroupMessagesImpl); + address oldImplAddress = address(groupMessagesImpl); + + bytes memory message = new bytes(78); + for (uint256 i = 0; i < message.length; i++) { + message[i] = bytes1(uint8(i % 256)); + } + + // Retrieve the implementation address directly from the proxy storage. + bytes32 rawImplAddress = vm.load(address(groupMessages), EIP1967_IMPL_SLOT); + address implementationAddress = address(uint160(uint256(rawImplAddress))); + assertEq(implementationAddress, oldImplAddress); + + // Initialize sequenceId to 1. The state should be preserved between upgrades. + vm.expectEmit(address(groupMessages)); + emit GroupMessages.MessageSent(GROUP_ID, message, 1); + groupMessages.addMessage(GROUP_ID, message); + + // Unauthorized upgrade attempts should revert. + vm.prank(unauthorized); + vm.expectRevert(revertRoleData(unauthorized)); + groupMessages.upgradeToAndCall(address(newGroupMessagesImpl), ""); + + // Authorized upgrade should succeed and emit UpgradeAuthorized event. + vm.expectEmit(address(groupMessages)); + emit GroupMessages.UpgradeAuthorized(address(this), address(newGroupMessagesImpl)); + groupMessages.upgradeToAndCall(address(newGroupMessagesImpl), ""); + + // Retrieve the new implementation address directly from the proxy storage. + rawImplAddress = vm.load(address(groupMessages), EIP1967_IMPL_SLOT); + implementationAddress = address(uint160(uint256(rawImplAddress))); + assertEq(implementationAddress, newImplAddress); + + // Next sequenceId should be 2. + vm.expectEmit(address(groupMessages)); + emit GroupMessages.MessageSent(GROUP_ID, message, 2); + groupMessages.addMessage(GROUP_ID, message); + } + + function revertRoleData(address _user) public pure returns (bytes memory) { + return abi.encodeWithSelector(IAccessControl.AccessControlUnauthorizedAccount.selector, _user, DEFAULT_ADMIN_ROLE); } -} +} \ No newline at end of file diff --git a/contracts/test/IdentityUpdates.t.sol b/contracts/test/IdentityUpdates.t.sol index f46e1e3e..f42aa9f8 100644 --- a/contracts/test/IdentityUpdates.t.sol +++ b/contracts/test/IdentityUpdates.t.sol @@ -1,23 +1,135 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.28; +import "forge-std/src/Vm.sol"; import {Test, console} from "forge-std/src/Test.sol"; -import {IdentityUpdates} from "../src/IdentityUpdates.sol"; +import {IdentityUpdates} from "src/IdentityUpdates.sol"; +import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; +import {Initializable} from "@openzeppelin-contracts-upgradeable/proxy/utils/Initializable.sol"; +import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; contract IdentityUpdatesTest is Test { - IdentityUpdates public identityUpdates; + bytes32 constant DEFAULT_ADMIN_ROLE = 0x00; + bytes32 constant EIP1967_IMPL_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + bytes32 constant INBOX_ID = 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef; + + IdentityUpdates identityUpdatesImpl; + ERC1967Proxy proxy; + IdentityUpdates identityUpdates; + + address admin = address(this); + address unauthorized = address(0x1); function setUp() public { - identityUpdates = new IdentityUpdates(); + identityUpdatesImpl = new IdentityUpdates(); + + proxy = new ERC1967Proxy( + address(identityUpdatesImpl), + abi.encodeWithSelector(identityUpdates.initialize.selector, admin) + ); + + identityUpdates = IdentityUpdates(address(proxy)); } - function test_AddIdentityUpdate1k() public { - bytes32 inboxId = bytes32(0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef); + function test_AddIdentityUpdateValid() public { bytes memory message = new bytes(1024); for (uint256 i = 0; i < message.length; i++) { message[i] = bytes1(uint8(i % 256)); // Set each byte to its index modulo 256 } - identityUpdates.addIdentityUpdate(inboxId, message); + identityUpdates.addIdentityUpdate(INBOX_ID, message); + } + + function testAddMessageInvalid() public { + bytes memory message = new bytes(103); + for (uint256 i = 0; i < message.length; i++) { + message[i] = bytes1(uint8(i % 256)); + } + + vm.expectRevert(IdentityUpdates.InvalidIdentityUpdate.selector); + identityUpdates.addIdentityUpdate(INBOX_ID, message); + } + + function testInvalidReinitialization() public { + vm.expectRevert(Initializable.InvalidInitialization.selector); + identityUpdates.initialize(admin); + } + + function testPauseUnpause() public { + identityUpdates.pause(); + + vm.prank(unauthorized); + vm.expectRevert(); + identityUpdates.unpause(); + + identityUpdates.unpause(); + + vm.prank(unauthorized); + vm.expectRevert(); + identityUpdates.pause(); + } + + function testRoles() public { + identityUpdates.grantRole(DEFAULT_ADMIN_ROLE, unauthorized); + + vm.startPrank(unauthorized); + identityUpdates.pause(); + identityUpdates.unpause(); + vm.stopPrank(); + + identityUpdates.revokeRole(DEFAULT_ADMIN_ROLE, unauthorized); + + vm.prank(unauthorized); + vm.expectRevert(revertRoleData(unauthorized)); + identityUpdates.pause(); + + identityUpdates.renounceRole(DEFAULT_ADMIN_ROLE, admin); + vm.expectRevert(revertRoleData(admin)); + identityUpdates.pause(); + } + + function testUpgradeImplementation() public { + IdentityUpdates newIdentityUpdatesImpl = new IdentityUpdates(); + address newImplAddress = address(newIdentityUpdatesImpl); + address oldImplAddress = address(identityUpdatesImpl); + + bytes memory message = new bytes(104); + for (uint256 i = 0; i < message.length; i++) { + message[i] = bytes1(uint8(i % 256)); + } + + // Retrieve the implementation address directly from the proxy storage. + bytes32 rawImplAddress = vm.load(address(identityUpdates), EIP1967_IMPL_SLOT); + address implementationAddress = address(uint160(uint256(rawImplAddress))); + assertEq(implementationAddress, oldImplAddress); + + // Initialize sequenceId to 1. The state should be preserved between upgrades. + vm.expectEmit(address(identityUpdates)); + emit IdentityUpdates.IdentityUpdateCreated(INBOX_ID, message, 1); + identityUpdates.addIdentityUpdate(INBOX_ID, message); + + // Unauthorized upgrade attempts should revert. + vm.prank(unauthorized); + vm.expectRevert(revertRoleData(unauthorized)); + identityUpdates.upgradeToAndCall(address(newIdentityUpdatesImpl), ""); + + // Authorized upgrade should succeed and emit UpgradeAuthorized event. + vm.expectEmit(address(identityUpdates)); + emit IdentityUpdates.UpgradeAuthorized(address(this), address(newIdentityUpdatesImpl)); + identityUpdates.upgradeToAndCall(address(newIdentityUpdatesImpl), ""); + + // Retrieve the new implementation address directly from the proxy storage. + rawImplAddress = vm.load(address(identityUpdates), EIP1967_IMPL_SLOT); + implementationAddress = address(uint160(uint256(rawImplAddress))); + assertEq(implementationAddress, newImplAddress); + + // Next sequenceId should be 2. + vm.expectEmit(address(identityUpdates)); + emit IdentityUpdates.IdentityUpdateCreated(INBOX_ID, message, 2); + identityUpdates.addIdentityUpdate(INBOX_ID, message); + } + + function revertRoleData(address _user) public pure returns (bytes memory) { + return abi.encodeWithSelector(IAccessControl.AccessControlUnauthorizedAccount.selector, _user, DEFAULT_ADMIN_ROLE); } } From 531feaed042364b2dc5ecc0ed0a5a99ae931a6e9 Mon Sep 17 00:00:00 2001 From: Borja Aranda Date: Thu, 19 Dec 2024 11:34:52 +0100 Subject: [PATCH 3/8] add finished scripts --- contracts/foundry.toml | 5 ++ contracts/script/DeployGroupMessages.s.sol | 55 +++++++++++++----- contracts/script/DeployIdentityUpdates.s.sol | 55 +++++++++++++----- .../31337/group_messages_deployment.json | 10 ++++ .../31337/identity_updates_deployment.json | 10 ++++ .../upgrades/UpgradeGroupMessages.s.sol | 55 ++++++++++++------ .../upgrades/UpgradeIdentityUpdates.s.sol | 57 +++++++++++++------ contracts/script/utils/Environment.sol | 9 +++ contracts/script/utils/Utils.sol | 36 ++++++++++++ contracts/src/GroupMessages.sol | 11 +++- contracts/src/IdentityUpdates.sol | 9 ++- contracts/test/GroupMessage.t.sol | 4 +- contracts/test/IdentityUpdates.t.sol | 4 ++ 13 files changed, 254 insertions(+), 66 deletions(-) create mode 100644 contracts/script/output/31337/group_messages_deployment.json create mode 100644 contracts/script/output/31337/identity_updates_deployment.json create mode 100644 contracts/script/utils/Environment.sol create mode 100644 contracts/script/utils/Utils.sol diff --git a/contracts/foundry.toml b/contracts/foundry.toml index acf06f0e..773ba6cd 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -12,6 +12,11 @@ remappings = [ "@openzeppelin-contracts-upgradeable/=dependencies/@openzeppelin-contracts-upgradeable-5.1.0/", "forge-std/=dependencies/forge-std-1.9.4/", ] +fs_permissions = [ + { access = "read-write", path = "script/output/31337"}, + { access = "read-write", path = "script/output/11155111"}, + { access = "read-write", path = "script/output/241320161"} +] [soldeer] recursive_deps = true diff --git a/contracts/script/DeployGroupMessages.s.sol b/contracts/script/DeployGroupMessages.s.sol index 8b49702e..8e273bdd 100644 --- a/contracts/script/DeployGroupMessages.s.sol +++ b/contracts/script/DeployGroupMessages.s.sol @@ -3,32 +3,59 @@ pragma solidity 0.8.28; import "forge-std/src/Script.sol"; import "forge-std/src/Vm.sol"; +import "./utils/Utils.sol"; +import "./utils/Environment.sol"; import "src/GroupMessages.sol"; import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; -contract DeployGroupMessages is Script { +contract DeployGroupMessages is Script, Utils, Environment { + GroupMessages groupMessagesImpl; + ERC1967Proxy proxy; + + address admin; + address deployer; + function run() external { + admin = vm.envAddress("XMTP_GROUP_MESSAGES_ADMIN_ADDRESS"); + require(admin != address(0), "XMTP_GROUP_MESSAGES_ADMIN_ADDRESS not set"); + require(admin.code.length == 0, "admin address is a contract, not an EOA"); + uint256 privateKey = vm.envUint("PRIVATE_KEY"); - address deployer = vm.addr(privateKey); + deployer = vm.addr(privateKey); vm.startBroadcast(privateKey); - // Step 1: Deploy the implementation contract. - GroupMessages groupMessagesImpl = new GroupMessages(); + // Deploy the implementation contract. + groupMessagesImpl = new GroupMessages(); + require(address(groupMessagesImpl) != address(0), "Implementation deployment failed"); - // Step 2: Deploy the proxy contract. - ERC1967Proxy proxy = + // Deploy the proxy contract. + proxy = new ERC1967Proxy( address(groupMessagesImpl), - abi.encodeWithSelector(GroupMessages.initialize.selector, deployer) - ); - - console.log( - '{"deployer":"%s","proxy":"%s","implementation":"%s"}', - deployer, - address(proxy), - address(groupMessagesImpl) + abi.encodeWithSelector(GroupMessages.initialize.selector, admin) ); vm.stopBroadcast(); + + _serializeDeploymentData(); + } + + function _serializeDeploymentData() internal { + string memory parent_object = "parent object"; + string memory addresses = "addresses"; + + string memory addressesOutput; + + addressesOutput = vm.serializeAddress(addresses, "groupMessagesDeployer", deployer); + addressesOutput = vm.serializeAddress(addresses, "groupMessagesProxyAdmin", admin); + addressesOutput = vm.serializeAddress(addresses, "groupMessagesProxy", address(proxy)); + addressesOutput = vm.serializeAddress(addresses, "groupMessagesImpl", address(groupMessagesImpl)); + + string memory finalJson; + finalJson = vm.serializeString(parent_object, addresses, addressesOutput); + finalJson = vm.serializeUint(parent_object, "deploymentBlock", block.number); + finalJson = vm.serializeUint(parent_object, "latestUpgradeBlock", block.number); + + writeOutput(finalJson, XMTP_GROUP_MESSAGES_OUTPUT_JSON); } } diff --git a/contracts/script/DeployIdentityUpdates.s.sol b/contracts/script/DeployIdentityUpdates.s.sol index cf969b33..99182568 100644 --- a/contracts/script/DeployIdentityUpdates.s.sol +++ b/contracts/script/DeployIdentityUpdates.s.sol @@ -3,32 +3,59 @@ pragma solidity 0.8.28; import "forge-std/src/Script.sol"; import "forge-std/src/Vm.sol"; +import "./utils/Utils.sol"; +import "./utils/Environment.sol"; import "src/IdentityUpdates.sol"; import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; -contract DeployIdentityUpdates is Script { +contract DeployIdentityUpdates is Script, Utils, Environment { + IdentityUpdates idUpdatesImpl; + ERC1967Proxy proxy; + + address admin; + address deployer; + function run() external { + admin = vm.envAddress("XMTP_IDENTITY_UPDATES_ADMIN_ADDRESS"); + require(admin != address(0), "XMTP_IDENTITY_UPDATES_ADMIN_ADDRESS not set"); + require(admin.code.length == 0, "admin address is a contract, not an EOA"); + uint256 privateKey = vm.envUint("PRIVATE_KEY"); - address deployer = vm.addr(privateKey); + deployer = vm.addr(privateKey); vm.startBroadcast(privateKey); - // Step 1: Deploy the implementation contract - IdentityUpdates idUpdatesImpl = new IdentityUpdates(); + // Deploy the implementation contract. + idUpdatesImpl = new IdentityUpdates(); + require(address(idUpdatesImpl) != address(0), "Implementation deployment failed"); - // Step 2: Deploy the proxy contract - ERC1967Proxy proxy = + // Deploy the proxy contract. + proxy = new ERC1967Proxy( address(idUpdatesImpl), - abi.encodeWithSelector(IdentityUpdates.initialize.selector, deployer) - ); - - console.log( - '{"deployer":"%s","proxy":"%s","implementation":"%s"}', - deployer, - address(proxy), - address(idUpdatesImpl) + abi.encodeWithSelector(IdentityUpdates.initialize.selector, admin) ); vm.stopBroadcast(); + + _serializeDeploymentData(); + } + + function _serializeDeploymentData() internal { + string memory parent_object = "parent object"; + string memory addresses = "addresses"; + + string memory addressesOutput; + + addressesOutput = vm.serializeAddress(addresses, "identityUpdatesDeployer", deployer); + addressesOutput = vm.serializeAddress(addresses, "identityUpdatesProxyAdmin", admin); + addressesOutput = vm.serializeAddress(addresses, "identityUpdatesProxy", address(proxy)); + addressesOutput = vm.serializeAddress(addresses, "identityUpdatesImpl", address(idUpdatesImpl)); + + string memory finalJson; + finalJson = vm.serializeString(parent_object, addresses, addressesOutput); + finalJson = vm.serializeUint(parent_object, "deploymentBlock", block.number); + finalJson = vm.serializeUint(parent_object, "latestUpgradeBlock", block.number); + + writeOutput(finalJson, XMTP_IDENTITY_UPDATES_OUTPUT_JSON); } } diff --git a/contracts/script/output/31337/group_messages_deployment.json b/contracts/script/output/31337/group_messages_deployment.json new file mode 100644 index 00000000..25f1f10b --- /dev/null +++ b/contracts/script/output/31337/group_messages_deployment.json @@ -0,0 +1,10 @@ +{ + "addresses": { + "groupMessagesDeployer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "groupMessagesImpl": "0xD0141E899a65C95a556fE2B27e5982A6DE7fDD7A", + "groupMessagesProxy": "0xD5ac451B0c50B9476107823Af206eD814a2e2580", + "groupMessagesProxyAdmin": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + }, + "deploymentBlock": 104, + "latestUpgradeBlock": 110 +} \ No newline at end of file diff --git a/contracts/script/output/31337/identity_updates_deployment.json b/contracts/script/output/31337/identity_updates_deployment.json new file mode 100644 index 00000000..5e6af9b5 --- /dev/null +++ b/contracts/script/output/31337/identity_updates_deployment.json @@ -0,0 +1,10 @@ +{ + "addresses": { + "identityUpdatesDeployer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "identityUpdatesImpl": "0x18E317A7D70d8fBf8e6E893616b52390EbBdb629", + "identityUpdatesProxy": "0x5067457698Fd6Fa1C6964e416b3f42713513B3dD", + "identityUpdatesProxyAdmin": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + }, + "deploymentBlock": 100, + "latestUpgradeBlock": 108 +} \ No newline at end of file diff --git a/contracts/script/upgrades/UpgradeGroupMessages.s.sol b/contracts/script/upgrades/UpgradeGroupMessages.s.sol index 38b04c0d..e1c8fbd2 100644 --- a/contracts/script/upgrades/UpgradeGroupMessages.s.sol +++ b/contracts/script/upgrades/UpgradeGroupMessages.s.sol @@ -3,34 +3,57 @@ pragma solidity 0.8.28; import "forge-std/src/Script.sol"; import "forge-std/src/Vm.sol"; +import "../utils/Utils.sol"; +import "../utils/Environment.sol"; import "src/GroupMessages.sol"; import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; -contract UpgradeGroupMessages is Script { - function run() external { - address proxyAddress = vm.envAddress("XMTP_GROUP_MESSAGES_PROXY_ADDRESS"); - require(proxyAddress != address(0), "XMTP_GROUP_MESSAGES_PROXY_ADDRESS not set"); +contract UpgradeGroupMessages is Script, Utils, Environment { + GroupMessages newImplementation; + GroupMessages proxy; + + address upgrader; + function run() external { uint256 privateKey = vm.envUint("PRIVATE_KEY"); - address upgrader = vm.addr(privateKey); + upgrader = vm.addr(privateKey); + vm.startBroadcast(privateKey); - // Step 1: Deploy the new implementation contract. - GroupMessages newImplementation = new GroupMessages(); + _initializeProxy(); - // Step 2: Initialize the proxy. - GroupMessages proxy = GroupMessages(proxyAddress); + // Deploy the new implementation contract. + newImplementation = new GroupMessages(); + require(address(newImplementation) != address(0), "Implementation deployment failed"); - // Step 3: Upgrade the proxy pointer to the new implementation. + // Upgrade the proxy pointer to the new implementation. proxy.upgradeToAndCall(address(newImplementation), ""); - console.log( - '{"upgrader":"%s","proxy":"%s","newImplementation":"%s"}', - upgrader, - address(proxy), - address(newImplementation) + vm.stopBroadcast(); + + _serializeUpgradeData(); + } + + function _initializeProxy() internal { + string memory fileContent = readOutput(XMTP_GROUP_MESSAGES_OUTPUT_JSON); + proxy = GroupMessages(stdJson.readAddress(fileContent, ".addresses.groupMessagesProxy")); + require(address(proxy) != address(0), "proxy address not set"); + require( + proxy.hasRole(proxy.DEFAULT_ADMIN_ROLE(), upgrader), + "Upgrader must have admin role" ); + } - vm.stopBroadcast(); + function _serializeUpgradeData() internal { + vm.writeJson( + vm.toString(address(newImplementation)), + getOutputPath(XMTP_GROUP_MESSAGES_OUTPUT_JSON), + ".addresses.groupMessagesImpl" + ); + vm.writeJson( + vm.toString(block.number), + getOutputPath(XMTP_GROUP_MESSAGES_OUTPUT_JSON), + ".latestUpgradeBlock" + ); } } diff --git a/contracts/script/upgrades/UpgradeIdentityUpdates.s.sol b/contracts/script/upgrades/UpgradeIdentityUpdates.s.sol index 4c9d2dd4..22ebbe7f 100644 --- a/contracts/script/upgrades/UpgradeIdentityUpdates.s.sol +++ b/contracts/script/upgrades/UpgradeIdentityUpdates.s.sol @@ -3,34 +3,57 @@ pragma solidity 0.8.28; import "forge-std/src/Script.sol"; import "forge-std/src/Vm.sol"; +import "../utils/Utils.sol"; +import "../utils/Environment.sol"; import "src/IdentityUpdates.sol"; import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; -contract UpgradeGroupMessages is Script { - function run() external { - address proxyAddress = vm.envAddress("XMTP_IDENTITY_UPDATES_PROXY_ADDRESS"); - require(proxyAddress != address(0), "XMTP_IDENTITY_UPDATES_PROXY_ADDRESS not set"); +contract UpgradeIdentityUpdates is Script, Utils, Environment { + IdentityUpdates newImplementation; + IdentityUpdates proxy; + + address upgrader; + function run() external { uint256 privateKey = vm.envUint("PRIVATE_KEY"); - address upgrader = vm.addr(privateKey); + upgrader = vm.addr(privateKey); + vm.startBroadcast(privateKey); - - // Step 1: Deploy the new implementation contract. - IdentityUpdates newImplementation = new IdentityUpdates(); - // Step 2: Initialize the proxy. - IdentityUpdates proxy = IdentityUpdates(proxyAddress); + _initializeProxy(); - // Step 3: Upgrade the proxy pointer to the new implementation. + // Deploy the new implementation contract. + newImplementation = new IdentityUpdates(); + require(address(newImplementation) != address(0), "Implementation deployment failed"); + + // Upgrade the proxy pointer to the new implementation. proxy.upgradeToAndCall(address(newImplementation), ""); - console.log( - '{"upgrader":"%s","proxy":"%s","newImplementation":"%s"}', - upgrader, - address(proxy), - address(newImplementation) + vm.stopBroadcast(); + + _serializeUpgradeData(); + } + + function _initializeProxy() internal { + string memory fileContent = readOutput(XMTP_IDENTITY_UPDATES_OUTPUT_JSON); + proxy = IdentityUpdates(stdJson.readAddress(fileContent, ".addresses.identityUpdatesProxy")); + require(address(proxy) != address(0), "proxy address not set"); + require( + proxy.hasRole(proxy.DEFAULT_ADMIN_ROLE(), upgrader), + "Upgrader must have admin role" ); + } - vm.stopBroadcast(); + function _serializeUpgradeData() internal { + vm.writeJson( + vm.toString(address(newImplementation)), + getOutputPath(XMTP_IDENTITY_UPDATES_OUTPUT_JSON), + ".addresses.identityUpdatesImpl" + ); + vm.writeJson( + vm.toString(block.number), + getOutputPath(XMTP_IDENTITY_UPDATES_OUTPUT_JSON), + ".latestUpgradeBlock" + ); } } diff --git a/contracts/script/utils/Environment.sol b/contracts/script/utils/Environment.sol new file mode 100644 index 00000000..14ab89d4 --- /dev/null +++ b/contracts/script/utils/Environment.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.28; + +import "forge-std/src/Script.sol"; + +contract Environment is Script { + string public constant XMTP_GROUP_MESSAGES_OUTPUT_JSON = "group_messages_deployment"; + string public constant XMTP_IDENTITY_UPDATES_OUTPUT_JSON = "identity_updates_deployment"; +} diff --git a/contracts/script/utils/Utils.sol b/contracts/script/utils/Utils.sol new file mode 100644 index 00000000..f9fb8fb0 --- /dev/null +++ b/contracts/script/utils/Utils.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.28; + +import "forge-std/src/Script.sol"; +import "forge-std/src/StdJson.sol"; + +contract Utils is Script { + function readInput(string memory inputFileName) internal view returns (string memory) { + string memory file = getInputPath(inputFileName); + return vm.readFile(file); + } + + function getInputPath(string memory inputFileName) internal view returns (string memory) { + string memory inputDir = string.concat(vm.projectRoot(), "/script/input/"); + string memory chainDir = string.concat(vm.toString(block.chainid), "/"); + string memory file = string.concat(inputFileName, ".json"); + return string.concat(inputDir, chainDir, file); + } + + function readOutput(string memory outputFileName) internal view returns (string memory) { + string memory file = getOutputPath(outputFileName); + return vm.readFile(file); + } + + function writeOutput(string memory outputJson, string memory outputFileName) internal { + string memory outputFilePath = getOutputPath(outputFileName); + vm.writeJson(outputJson, outputFilePath); + } + + function getOutputPath(string memory outputFileName) internal view returns (string memory) { + string memory outputDir = string.concat(vm.projectRoot(), "/script/output/"); + string memory chainDir = string.concat(vm.toString(block.chainid), "/"); + string memory outputFilePath = string.concat(outputDir, chainDir, outputFileName, ".json"); + return outputFilePath; + } +} \ No newline at end of file diff --git a/contracts/src/GroupMessages.sol b/contracts/src/GroupMessages.sol index 20482eeb..0f2a3177 100644 --- a/contracts/src/GroupMessages.sol +++ b/contracts/src/GroupMessages.sol @@ -11,6 +11,11 @@ contract GroupMessages is Initializable, AccessControlUpgradeable, UUPSUpgradeab event MessageSent(bytes32 groupId, bytes message, uint64 sequenceId); event UpgradeAuthorized(address deployer, address newImplementation); + error InvalidIdentityUpdateSize(uint256 actualSize, uint256 minSize, uint256 maxSize); + + uint256 private constant MIN_PAYLOAD_SIZE = 78; + uint256 private constant MAX_PAYLOAD_SIZE = 4_194_304; + error InvalidMessage(); uint64 private sequenceId; @@ -42,8 +47,10 @@ contract GroupMessages is Initializable, AccessControlUpgradeable, UUPSUpgradeab /// @param groupId The group ID. /// @param message The message in bytes. function addMessage(bytes32 groupId, bytes calldata message) public whenNotPaused { - /// @dev 78 bytes contains the minimum length of a valid message. - require(message.length >= 78, InvalidMessage()); + require( + message.length >= MIN_PAYLOAD_SIZE && message.length <= MAX_PAYLOAD_SIZE, + InvalidMessage() + ); /// @dev Incrementing the sequence ID is safe here due to the extremely large limit of uint64. unchecked { diff --git a/contracts/src/IdentityUpdates.sol b/contracts/src/IdentityUpdates.sol index b2bc84ec..0c6686a7 100644 --- a/contracts/src/IdentityUpdates.sol +++ b/contracts/src/IdentityUpdates.sol @@ -13,6 +13,9 @@ contract IdentityUpdates is Initializable, AccessControlUpgradeable, UUPSUpgrade error InvalidIdentityUpdate(); + uint256 private constant MIN_PAYLOAD_SIZE = 104; + uint256 private constant MAX_PAYLOAD_SIZE = 4_194_304; + uint64 private sequenceId; /// @dev Reserved storage gap for future upgrades @@ -42,8 +45,10 @@ contract IdentityUpdates is Initializable, AccessControlUpgradeable, UUPSUpgrade /// @param inboxId The inbox ID. /// @param update The identity update in bytes. function addIdentityUpdate(bytes32 inboxId, bytes calldata update) public whenNotPaused { - /// @dev 104 bytes contains the minimum length of a valid IdentityUpdate. - require(update.length >= 104, InvalidIdentityUpdate()); + require( + update.length >= MIN_PAYLOAD_SIZE && update.length <= MAX_PAYLOAD_SIZE, + InvalidIdentityUpdate() + ); /// @dev Incrementing the sequence ID is safe here due to the extremely large limit of uint64. unchecked { diff --git a/contracts/test/GroupMessage.t.sol b/contracts/test/GroupMessage.t.sol index 543fd8cf..07000306 100644 --- a/contracts/test/GroupMessage.t.sol +++ b/contracts/test/GroupMessage.t.sol @@ -47,7 +47,7 @@ contract GroupMessagesTest is Test { bytes memory message = new bytes(77); for (uint256 i = 0; i < message.length; i++) { message[i] = bytes1(uint8(i % 256)); - } + } vm.expectRevert(GroupMessages.InvalidMessage.selector); groupMessages.addMessage(GROUP_ID, message); @@ -60,12 +60,14 @@ contract GroupMessagesTest is Test { function testPauseUnpause() public { groupMessages.pause(); + assertTrue(groupMessages.paused()); vm.prank(unauthorized); vm.expectRevert(); groupMessages.unpause(); groupMessages.unpause(); + assertFalse(groupMessages.paused()); vm.prank(unauthorized); vm.expectRevert(); diff --git a/contracts/test/IdentityUpdates.t.sol b/contracts/test/IdentityUpdates.t.sol index f42aa9f8..6a2bf3a5 100644 --- a/contracts/test/IdentityUpdates.t.sol +++ b/contracts/test/IdentityUpdates.t.sol @@ -37,6 +37,8 @@ contract IdentityUpdatesTest is Test { message[i] = bytes1(uint8(i % 256)); // Set each byte to its index modulo 256 } + vm.expectEmit(address(identityUpdates)); + emit IdentityUpdates.IdentityUpdateCreated(INBOX_ID, message, 1); identityUpdates.addIdentityUpdate(INBOX_ID, message); } @@ -57,12 +59,14 @@ contract IdentityUpdatesTest is Test { function testPauseUnpause() public { identityUpdates.pause(); + assertTrue(identityUpdates.paused()); vm.prank(unauthorized); vm.expectRevert(); identityUpdates.unpause(); identityUpdates.unpause(); + assertFalse(identityUpdates.paused()); vm.prank(unauthorized); vm.expectRevert(); From e29d1c0f1d49748346cd2f10619d7a2e9b31cd59 Mon Sep 17 00:00:00 2001 From: Borja Aranda Date: Thu, 19 Dec 2024 14:25:38 +0100 Subject: [PATCH 4/8] include finished contracts, ci and readme --- contracts/README.md | 100 +++++++++---- contracts/script/DeployGroupMessages.s.sol | 6 +- contracts/script/DeployIdentityUpdates.s.sol | 5 +- .../31337/group_messages_deployment.json | 8 +- .../31337/identity_updates_deployment.json | 6 +- .../upgrades/UpgradeGroupMessages.s.sol | 11 +- .../upgrades/UpgradeIdentityUpdates.s.sol | 11 +- contracts/script/utils/Utils.sol | 2 +- contracts/src/GroupMessages.sol | 41 ++++-- contracts/src/IdentityUpdates.sol | 40 ++++-- contracts/test/GroupMessage.t.sol | 135 +++++++++++------ contracts/test/IdentityUpdates.t.sol | 136 ++++++++++++------ contracts/test/utils/Utils.sol | 18 +++ dev/contracts/.env | 8 +- dev/contracts/common | 41 ++++++ dev/contracts/deploy-local | 19 +-- dev/contracts/deploy-testnet | 5 +- dev/docker/up | 1 + dev/up | 6 +- 19 files changed, 427 insertions(+), 172 deletions(-) create mode 100644 contracts/test/utils/Utils.sol create mode 100644 dev/contracts/common diff --git a/contracts/README.md b/contracts/README.md index 9265b455..75271f03 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -1,66 +1,112 @@ -## Foundry +# XMTP Contracts -**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.** +- [XMTP Contracts](#xmtp-contracts) + - [Messages Contracts](#messages-contracts) + - [XMTP Node Registry](#xmtp-node-registry) + - [Usage](#usage) + - [Prerequisites](#prerequisites) + - [Install](#install) + - [Test](#test) + - [Run static analysis](#run-static-analysis) + - [Scripts](#scripts) + - [Messages contracts](#messages-contracts-1) + - [Node registry](#node-registry) -Foundry consists of: +**⚠️ Experimental:** This software is in early development. Expect frequent changes and unresolved issues. -- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools). -- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data. -- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network. -- **Chisel**: Fast, utilitarian, and verbose solidity REPL. +This repository contains all the smart contracts that underpin the XMTP decentralized network. -## Documentation +## Messages Contracts -https://book.getfoundry.sh/ +The messages contracts manage the blockchain state for `GroupMessages` and `IdentityUpdates` sent by clients to the network. + +These contracts ensure transparency and provide a historical record of state changes. + +## XMTP Node Registry + +The `XMTP Node Registry` maintains a blockchain-based record of all node operators participating in the XMTP network. This registry serves as a source of truth for the network's active node participants, contributing to the network's integrity. + +The registry is currently implemented following the [ERC721](https://eips.ethereum.org/EIPS/eip-721) standard. ## Usage -### Build +The project is built with the `Foundry` framework, and dependency management is handled using `soldeer`. + +Additionally, it uses `slither` for static analysis. + +### Prerequisites + +[Install foundry](https://book.getfoundry.sh/getting-started/installation) + +[Install slither](https://github.com/crytic/slither?tab=readme-ov-file#how-to-install) + +### Install + +As the project uses `soldeer`, update the dependencies by running: ```shell -$ forge build +forge soldeer update ``` -### Test +Build the contracts: ```shell -$ forge test +forge build ``` -### Format +### Test + +To run the unit tests: ```shell -$ forge fmt +forge test ``` -### Gas Snapshots +### Run static analysis + +Run the analysis with `slither`: ```shell -$ forge snapshot +slither . ``` -### Anvil +## Scripts + +The project includes deployer and upgrade scripts. + +### Messages contracts + +- Configure the environment by providing an `.env` file, with this content: ```shell -$ anvil +### Main configuration +PRIVATE_KEY=0xYourPrivateKey # Private key of the EOA deploying the contracts + +### XMTP deployment configuration +XMTP_GROUP_MESSAGES_ADMIN_ADDRESS=0x12345abcdf # the EOA assuming the admin role in the GroupMessages contract. +XMTP_IDENTITY_UPDATES_ADMIN_ADDRESS=0x12345abcdf # the EOA assuming the admin role in the IdentityUpdates contract. ``` -### Deploy +- Run the desired script with: ```shell -$ forge script script/Counter.s.sol:CounterScript --rpc-url --private-key +forge script --rpc-url --broadcast ``` -### Cast +Example: ```shell -$ cast +forge script --rpc-url http://localhost:7545 --broadcast script/DeployGroupMessages.s.sol ``` -### Help +The scripts output the deployment and upgrade in the `output` folder. + +### Node registry + +**⚠️:** The node registry hasn't been fully migrated to forge scripts. + +- Deploy with `forge create`: ```shell -$ forge --help -$ anvil --help -$ cast --help +forge create --broadcast --legacy --json --rpc-url $DOCKER_RPC_URL --private-key $PRIVATE_KEY "src/Nodes.sol:Nodes" ``` diff --git a/contracts/script/DeployGroupMessages.s.sol b/contracts/script/DeployGroupMessages.s.sol index 8e273bdd..3c9be6e0 100644 --- a/contracts/script/DeployGroupMessages.s.sol +++ b/contracts/script/DeployGroupMessages.s.sol @@ -29,10 +29,8 @@ contract DeployGroupMessages is Script, Utils, Environment { require(address(groupMessagesImpl) != address(0), "Implementation deployment failed"); // Deploy the proxy contract. - proxy = - new ERC1967Proxy( - address(groupMessagesImpl), - abi.encodeWithSelector(GroupMessages.initialize.selector, admin) + proxy = new ERC1967Proxy( + address(groupMessagesImpl), abi.encodeWithSelector(GroupMessages.initialize.selector, admin) ); vm.stopBroadcast(); diff --git a/contracts/script/DeployIdentityUpdates.s.sol b/contracts/script/DeployIdentityUpdates.s.sol index 99182568..abe9ae5b 100644 --- a/contracts/script/DeployIdentityUpdates.s.sol +++ b/contracts/script/DeployIdentityUpdates.s.sol @@ -30,10 +30,7 @@ contract DeployIdentityUpdates is Script, Utils, Environment { // Deploy the proxy contract. proxy = - new ERC1967Proxy( - address(idUpdatesImpl), - abi.encodeWithSelector(IdentityUpdates.initialize.selector, admin) - ); + new ERC1967Proxy(address(idUpdatesImpl), abi.encodeWithSelector(IdentityUpdates.initialize.selector, admin)); vm.stopBroadcast(); diff --git a/contracts/script/output/31337/group_messages_deployment.json b/contracts/script/output/31337/group_messages_deployment.json index 25f1f10b..d22c1632 100644 --- a/contracts/script/output/31337/group_messages_deployment.json +++ b/contracts/script/output/31337/group_messages_deployment.json @@ -1,10 +1,10 @@ { "addresses": { "groupMessagesDeployer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "groupMessagesImpl": "0xD0141E899a65C95a556fE2B27e5982A6DE7fDD7A", - "groupMessagesProxy": "0xD5ac451B0c50B9476107823Af206eD814a2e2580", + "groupMessagesImpl": "0xe8D2A1E88c91DCd5433208d4152Cc4F399a7e91d", + "groupMessagesProxy": "0x5067457698Fd6Fa1C6964e416b3f42713513B3dD", "groupMessagesProxyAdmin": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" }, - "deploymentBlock": 104, - "latestUpgradeBlock": 110 + "deploymentBlock": 100, + "latestUpgradeBlock": 100 } \ No newline at end of file diff --git a/contracts/script/output/31337/identity_updates_deployment.json b/contracts/script/output/31337/identity_updates_deployment.json index 5e6af9b5..1ec61bc4 100644 --- a/contracts/script/output/31337/identity_updates_deployment.json +++ b/contracts/script/output/31337/identity_updates_deployment.json @@ -2,9 +2,9 @@ "addresses": { "identityUpdatesDeployer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "identityUpdatesImpl": "0x18E317A7D70d8fBf8e6E893616b52390EbBdb629", - "identityUpdatesProxy": "0x5067457698Fd6Fa1C6964e416b3f42713513B3dD", + "identityUpdatesProxy": "0x4b6aB5F819A515382B0dEB6935D793817bB4af28", "identityUpdatesProxyAdmin": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" }, - "deploymentBlock": 100, - "latestUpgradeBlock": 108 + "deploymentBlock": 102, + "latestUpgradeBlock": 102 } \ No newline at end of file diff --git a/contracts/script/upgrades/UpgradeGroupMessages.s.sol b/contracts/script/upgrades/UpgradeGroupMessages.s.sol index e1c8fbd2..b363593d 100644 --- a/contracts/script/upgrades/UpgradeGroupMessages.s.sol +++ b/contracts/script/upgrades/UpgradeGroupMessages.s.sol @@ -38,10 +38,7 @@ contract UpgradeGroupMessages is Script, Utils, Environment { string memory fileContent = readOutput(XMTP_GROUP_MESSAGES_OUTPUT_JSON); proxy = GroupMessages(stdJson.readAddress(fileContent, ".addresses.groupMessagesProxy")); require(address(proxy) != address(0), "proxy address not set"); - require( - proxy.hasRole(proxy.DEFAULT_ADMIN_ROLE(), upgrader), - "Upgrader must have admin role" - ); + require(proxy.hasRole(proxy.DEFAULT_ADMIN_ROLE(), upgrader), "Upgrader must have admin role"); } function _serializeUpgradeData() internal { @@ -50,10 +47,6 @@ contract UpgradeGroupMessages is Script, Utils, Environment { getOutputPath(XMTP_GROUP_MESSAGES_OUTPUT_JSON), ".addresses.groupMessagesImpl" ); - vm.writeJson( - vm.toString(block.number), - getOutputPath(XMTP_GROUP_MESSAGES_OUTPUT_JSON), - ".latestUpgradeBlock" - ); + vm.writeJson(vm.toString(block.number), getOutputPath(XMTP_GROUP_MESSAGES_OUTPUT_JSON), ".latestUpgradeBlock"); } } diff --git a/contracts/script/upgrades/UpgradeIdentityUpdates.s.sol b/contracts/script/upgrades/UpgradeIdentityUpdates.s.sol index 22ebbe7f..f0597611 100644 --- a/contracts/script/upgrades/UpgradeIdentityUpdates.s.sol +++ b/contracts/script/upgrades/UpgradeIdentityUpdates.s.sol @@ -38,10 +38,7 @@ contract UpgradeIdentityUpdates is Script, Utils, Environment { string memory fileContent = readOutput(XMTP_IDENTITY_UPDATES_OUTPUT_JSON); proxy = IdentityUpdates(stdJson.readAddress(fileContent, ".addresses.identityUpdatesProxy")); require(address(proxy) != address(0), "proxy address not set"); - require( - proxy.hasRole(proxy.DEFAULT_ADMIN_ROLE(), upgrader), - "Upgrader must have admin role" - ); + require(proxy.hasRole(proxy.DEFAULT_ADMIN_ROLE(), upgrader), "Upgrader must have admin role"); } function _serializeUpgradeData() internal { @@ -50,10 +47,6 @@ contract UpgradeIdentityUpdates is Script, Utils, Environment { getOutputPath(XMTP_IDENTITY_UPDATES_OUTPUT_JSON), ".addresses.identityUpdatesImpl" ); - vm.writeJson( - vm.toString(block.number), - getOutputPath(XMTP_IDENTITY_UPDATES_OUTPUT_JSON), - ".latestUpgradeBlock" - ); + vm.writeJson(vm.toString(block.number), getOutputPath(XMTP_IDENTITY_UPDATES_OUTPUT_JSON), ".latestUpgradeBlock"); } } diff --git a/contracts/script/utils/Utils.sol b/contracts/script/utils/Utils.sol index f9fb8fb0..deac7579 100644 --- a/contracts/script/utils/Utils.sol +++ b/contracts/script/utils/Utils.sol @@ -33,4 +33,4 @@ contract Utils is Script { string memory outputFilePath = string.concat(outputDir, chainDir, outputFileName, ".json"); return outputFilePath; } -} \ No newline at end of file +} diff --git a/contracts/src/GroupMessages.sol b/contracts/src/GroupMessages.sol index 0f2a3177..912fbdb3 100644 --- a/contracts/src/GroupMessages.sol +++ b/contracts/src/GroupMessages.sol @@ -8,24 +8,39 @@ import "@openzeppelin-contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; /// @title XMTP Group Messages Contract contract GroupMessages is Initializable, AccessControlUpgradeable, UUPSUpgradeable, PausableUpgradeable { + /// @notice Emitted when a message is sent. + /// @param groupId The group ID. + /// @param message The message in bytes. Contains the full mls group message payload. + /// @param sequenceId The unique sequence ID of the message. event MessageSent(bytes32 groupId, bytes message, uint64 sequenceId); - event UpgradeAuthorized(address deployer, address newImplementation); - error InvalidIdentityUpdateSize(uint256 actualSize, uint256 minSize, uint256 maxSize); + /// @notice Emitted when an upgrade is authorized. + /// @param upgrader The EOA authorizing the upgrade. + /// @param newImplementation The address of the new implementation. + event UpgradeAuthorized(address upgrader, address newImplementation); + + // Custom errors + error ZeroAdminAddress(); + error InvalidPayloadSize(uint256 actualSize, uint256 minSize, uint256 maxSize); - uint256 private constant MIN_PAYLOAD_SIZE = 78; - uint256 private constant MAX_PAYLOAD_SIZE = 4_194_304; + /// @dev Minimum valid payload size (in bytes). + uint256 public constant MIN_PAYLOAD_SIZE = 78; - error InvalidMessage(); + /// @dev Maximum valid payload size (4 MB). + uint256 public constant MAX_PAYLOAD_SIZE = 4_194_304; + // State variables uint64 private sequenceId; /// @dev Reserved storage gap for future upgrades uint256[50] private __gap; + // Initialization /// @notice Initializes the contract with the deployer as admin. + /// @param _admin The address of the admin. function initialize(address _admin) public initializer { - require(_admin != address(0), "Admin address cannot be zero"); + require(_admin != address(0), ZeroAdminAddress()); + __UUPSUpgradeable_init(); __AccessControl_init(); __Pausable_init(); @@ -33,26 +48,31 @@ contract GroupMessages is Initializable, AccessControlUpgradeable, UUPSUpgradeab _grantRole(DEFAULT_ADMIN_ROLE, _admin); } - /// @notice Pauses the contract. + // Pausable functionality + /// @notice Pauses the contract, restricting certain actions. + /// @dev Callable only by accounts with the DEFAULT_ADMIN_ROLE. function pause() public onlyRole(DEFAULT_ADMIN_ROLE) { _pause(); } - /// @notice Unpauses the contract. + /// @notice Unpauses the contract, allowing normal operations. + /// @dev Callable only by accounts with the DEFAULT_ADMIN_ROLE. function unpause() public onlyRole(DEFAULT_ADMIN_ROLE) { _unpause(); } + // Messaging functionality /// @notice Adds a message to the group. /// @param groupId The group ID. /// @param message The message in bytes. + /// @dev Ensures the message length is within the allowed range and increments the sequence ID. function addMessage(bytes32 groupId, bytes calldata message) public whenNotPaused { require( message.length >= MIN_PAYLOAD_SIZE && message.length <= MAX_PAYLOAD_SIZE, - InvalidMessage() + InvalidPayloadSize(message.length, MIN_PAYLOAD_SIZE, MAX_PAYLOAD_SIZE) ); - /// @dev Incrementing the sequence ID is safe here due to the extremely large limit of uint64. + // Increment sequence ID safely using unchecked to save gas. unchecked { sequenceId++; } @@ -60,6 +80,7 @@ contract GroupMessages is Initializable, AccessControlUpgradeable, UUPSUpgradeab emit MessageSent(groupId, message, sequenceId); } + // Upgradeability /// @dev Authorizes the upgrade of the contract. /// @param newImplementation The address of the new implementation. function _authorizeUpgrade(address newImplementation) internal override onlyRole(DEFAULT_ADMIN_ROLE) { diff --git a/contracts/src/IdentityUpdates.sol b/contracts/src/IdentityUpdates.sol index 0c6686a7..7e6eaeca 100644 --- a/contracts/src/IdentityUpdates.sol +++ b/contracts/src/IdentityUpdates.sol @@ -8,22 +8,39 @@ import "@openzeppelin-contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; /// @title XMTP Identity Updates Contract contract IdentityUpdates is Initializable, AccessControlUpgradeable, UUPSUpgradeable, PausableUpgradeable { + /// @notice Emitted when an identity update is sent. + /// @param inboxId The inbox ID. + /// @param update The identity update in bytes. Contains the full mls identity update payload. + /// @param sequenceId The unique sequence ID of the identity update. event IdentityUpdateCreated(bytes32 inboxId, bytes update, uint64 sequenceId); - event UpgradeAuthorized(address deployer, address newImplementation); - error InvalidIdentityUpdate(); + /// @notice Emitted when an upgrade is authorized. + /// @param upgrader The EOA authorizing the upgrade. + /// @param newImplementation The address of the new implementation. + event UpgradeAuthorized(address upgrader, address newImplementation); + + // Custom errors + error ZeroAdminAddress(); + error InvalidPayloadSize(uint256 actualSize, uint256 minSize, uint256 maxSize); - uint256 private constant MIN_PAYLOAD_SIZE = 104; - uint256 private constant MAX_PAYLOAD_SIZE = 4_194_304; + /// @dev Minimum valid payload size (in bytes). + uint256 public constant MIN_PAYLOAD_SIZE = 104; + /// @dev Maximum valid payload size (4 MB). + uint256 public constant MAX_PAYLOAD_SIZE = 4_194_304; + + // State variables uint64 private sequenceId; /// @dev Reserved storage gap for future upgrades uint256[50] private __gap; + // Initialization /// @notice Initializes the contract with the deployer as admin. + /// @param _admin The address of the admin. function initialize(address _admin) public initializer { - require(_admin != address(0), "Admin address cannot be zero"); + require(_admin != address(0), ZeroAdminAddress()); + __UUPSUpgradeable_init(); __AccessControl_init(); __Pausable_init(); @@ -31,26 +48,30 @@ contract IdentityUpdates is Initializable, AccessControlUpgradeable, UUPSUpgrade _grantRole(DEFAULT_ADMIN_ROLE, _admin); } - /// @notice Pauses the contract. + // Pausable functionality + /// @notice Pauses the contract, restricting certain actions. + /// @dev Callable only by accounts with the DEFAULT_ADMIN_ROLE. function pause() public onlyRole(DEFAULT_ADMIN_ROLE) { _pause(); } - /// @notice Unpauses the contract. + /// @notice Unpauses the contract, allowing normal operations. + /// @dev Callable only by accounts with the DEFAULT_ADMIN_ROLE. function unpause() public onlyRole(DEFAULT_ADMIN_ROLE) { _unpause(); } + // IdentityUpdate functionality /// @notice Adds an identity update to an specific inbox ID. /// @param inboxId The inbox ID. /// @param update The identity update in bytes. function addIdentityUpdate(bytes32 inboxId, bytes calldata update) public whenNotPaused { require( update.length >= MIN_PAYLOAD_SIZE && update.length <= MAX_PAYLOAD_SIZE, - InvalidIdentityUpdate() + InvalidPayloadSize(update.length, MIN_PAYLOAD_SIZE, MAX_PAYLOAD_SIZE) ); - /// @dev Incrementing the sequence ID is safe here due to the extremely large limit of uint64. + // Increment sequence ID safely using unchecked to save gas. unchecked { sequenceId++; } @@ -58,6 +79,7 @@ contract IdentityUpdates is Initializable, AccessControlUpgradeable, UUPSUpgrade emit IdentityUpdateCreated(inboxId, update, sequenceId); } + // Upgradeability /// @dev Authorizes the upgrade of the contract. /// @param newImplementation The address of the new implementation. function _authorizeUpgrade(address newImplementation) internal override onlyRole(DEFAULT_ADMIN_ROLE) { diff --git a/contracts/test/GroupMessage.t.sol b/contracts/test/GroupMessage.t.sol index 07000306..72c1abf9 100644 --- a/contracts/test/GroupMessage.t.sol +++ b/contracts/test/GroupMessage.t.sol @@ -3,16 +3,14 @@ pragma solidity 0.8.28; import "forge-std/src/Vm.sol"; import {Test, console} from "forge-std/src/Test.sol"; +import {Utils} from "test/utils/Utils.sol"; import {GroupMessages} from "src/GroupMessages.sol"; +import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; import {Initializable} from "@openzeppelin-contracts-upgradeable/proxy/utils/Initializable.sol"; -import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; - -contract GroupMessagesTest is Test { - bytes32 constant DEFAULT_ADMIN_ROLE = 0x00; - bytes32 constant EIP1967_IMPL_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; - bytes32 constant GROUP_ID = 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef; +import {PausableUpgradeable} from "@openzeppelin-contracts-upgradeable/utils/PausableUpgradeable.sol"; +contract GroupMessagesTest is Test, GroupMessages, Utils { GroupMessages groupMessagesImpl; ERC1967Proxy proxy; GroupMessages groupMessages; @@ -24,33 +22,79 @@ contract GroupMessagesTest is Test { groupMessagesImpl = new GroupMessages(); proxy = new ERC1967Proxy( - address(groupMessagesImpl), - abi.encodeWithSelector(GroupMessages.initialize.selector, admin) + address(groupMessagesImpl), abi.encodeWithSelector(GroupMessages.initialize.selector, admin) ); groupMessages = GroupMessages(address(proxy)); } function testAddMessageValid() public { - bytes memory message = new bytes(1024); - for (uint256 i = 0; i < message.length; i++) { - message[i] = bytes1(uint8(i % 256)); // Set each byte to its index modulo 256 - } + bytes memory message = _generatePayload(MIN_PAYLOAD_SIZE); + + vm.expectEmit(address(groupMessages)); + emit GroupMessages.MessageSent(ID, message, 1); + + groupMessages.addMessage(ID, message); + } + + function testAddMessageWithMaxPayload() public { + bytes memory message = _generatePayload(MAX_PAYLOAD_SIZE); vm.expectEmit(address(groupMessages)); - emit GroupMessages.MessageSent(GROUP_ID, message, 1); + emit GroupMessages.MessageSent(ID, message, 1); + + groupMessages.addMessage(ID, message); + } + + function testAddMessageTooSmall() public { + bytes memory message = _generatePayload(MIN_PAYLOAD_SIZE - 1); + + vm.expectRevert( + abi.encodeWithSelector( + GroupMessages.InvalidPayloadSize.selector, message.length, MIN_PAYLOAD_SIZE, MAX_PAYLOAD_SIZE + ) + ); + + groupMessages.addMessage(ID, message); + } + + function testAddMessageTooBig() public { + bytes memory message = _generatePayload(MAX_PAYLOAD_SIZE + 1); + + vm.expectRevert( + abi.encodeWithSelector( + GroupMessages.InvalidPayloadSize.selector, message.length, MIN_PAYLOAD_SIZE, MAX_PAYLOAD_SIZE + ) + ); + + groupMessages.addMessage(ID, message); + } + + function testAddMessageWhenPaused() public { + bytes memory message = _generatePayload(MIN_PAYLOAD_SIZE); + + groupMessages.pause(); + assertTrue(groupMessages.paused()); - groupMessages.addMessage(GROUP_ID, message); + vm.expectRevert(abi.encodeWithSelector(PausableUpgradeable.EnforcedPause.selector)); + + groupMessages.addMessage(ID, message); } - function testAddMessageInvalid() public { - bytes memory message = new bytes(77); - for (uint256 i = 0; i < message.length; i++) { - message[i] = bytes1(uint8(i % 256)); - } + function testSequenceIdIncrement() public { + bytes memory message = _generatePayload(MIN_PAYLOAD_SIZE); + + vm.expectEmit(address(groupMessages)); + emit GroupMessages.MessageSent(ID, message, 1); + groupMessages.addMessage(ID, message); + + vm.expectEmit(address(groupMessages)); + emit GroupMessages.MessageSent(ID, message, 2); + groupMessages.addMessage(ID, message); - vm.expectRevert(GroupMessages.InvalidMessage.selector); - groupMessages.addMessage(GROUP_ID, message); + vm.expectEmit(address(groupMessages)); + emit GroupMessages.MessageSent(ID, message, 3); + groupMessages.addMessage(ID, message); } function testInvalidReinitialization() public { @@ -63,14 +107,22 @@ contract GroupMessagesTest is Test { assertTrue(groupMessages.paused()); vm.prank(unauthorized); - vm.expectRevert(); + vm.expectRevert( + abi.encodeWithSelector( + IAccessControl.AccessControlUnauthorizedAccount.selector, unauthorized, DEFAULT_ADMIN_ROLE + ) + ); groupMessages.unpause(); groupMessages.unpause(); assertFalse(groupMessages.paused()); vm.prank(unauthorized); - vm.expectRevert(); + vm.expectRevert( + abi.encodeWithSelector( + IAccessControl.AccessControlUnauthorizedAccount.selector, unauthorized, DEFAULT_ADMIN_ROLE + ) + ); groupMessages.pause(); } @@ -85,11 +137,17 @@ contract GroupMessagesTest is Test { groupMessages.revokeRole(DEFAULT_ADMIN_ROLE, unauthorized); vm.prank(unauthorized); - vm.expectRevert(revertRoleData(unauthorized)); + vm.expectRevert( + abi.encodeWithSelector( + IAccessControl.AccessControlUnauthorizedAccount.selector, unauthorized, DEFAULT_ADMIN_ROLE + ) + ); groupMessages.pause(); groupMessages.renounceRole(DEFAULT_ADMIN_ROLE, admin); - vm.expectRevert(revertRoleData(admin)); + vm.expectRevert( + abi.encodeWithSelector(IAccessControl.AccessControlUnauthorizedAccount.selector, admin, DEFAULT_ADMIN_ROLE) + ); groupMessages.pause(); } @@ -97,11 +155,8 @@ contract GroupMessagesTest is Test { GroupMessages newGroupMessagesImpl = new GroupMessages(); address newImplAddress = address(newGroupMessagesImpl); address oldImplAddress = address(groupMessagesImpl); - - bytes memory message = new bytes(78); - for (uint256 i = 0; i < message.length; i++) { - message[i] = bytes1(uint8(i % 256)); - } + + bytes memory message = _generatePayload(MIN_PAYLOAD_SIZE); // Retrieve the implementation address directly from the proxy storage. bytes32 rawImplAddress = vm.load(address(groupMessages), EIP1967_IMPL_SLOT); @@ -110,12 +165,16 @@ contract GroupMessagesTest is Test { // Initialize sequenceId to 1. The state should be preserved between upgrades. vm.expectEmit(address(groupMessages)); - emit GroupMessages.MessageSent(GROUP_ID, message, 1); - groupMessages.addMessage(GROUP_ID, message); + emit GroupMessages.MessageSent(ID, message, 1); + groupMessages.addMessage(ID, message); // Unauthorized upgrade attempts should revert. vm.prank(unauthorized); - vm.expectRevert(revertRoleData(unauthorized)); + vm.expectRevert( + abi.encodeWithSelector( + IAccessControl.AccessControlUnauthorizedAccount.selector, unauthorized, DEFAULT_ADMIN_ROLE + ) + ); groupMessages.upgradeToAndCall(address(newGroupMessagesImpl), ""); // Authorized upgrade should succeed and emit UpgradeAuthorized event. @@ -130,11 +189,7 @@ contract GroupMessagesTest is Test { // Next sequenceId should be 2. vm.expectEmit(address(groupMessages)); - emit GroupMessages.MessageSent(GROUP_ID, message, 2); - groupMessages.addMessage(GROUP_ID, message); - } - - function revertRoleData(address _user) public pure returns (bytes memory) { - return abi.encodeWithSelector(IAccessControl.AccessControlUnauthorizedAccount.selector, _user, DEFAULT_ADMIN_ROLE); + emit GroupMessages.MessageSent(ID, message, 2); + groupMessages.addMessage(ID, message); } -} \ No newline at end of file +} diff --git a/contracts/test/IdentityUpdates.t.sol b/contracts/test/IdentityUpdates.t.sol index 6a2bf3a5..07691567 100644 --- a/contracts/test/IdentityUpdates.t.sol +++ b/contracts/test/IdentityUpdates.t.sol @@ -3,16 +3,14 @@ pragma solidity 0.8.28; import "forge-std/src/Vm.sol"; import {Test, console} from "forge-std/src/Test.sol"; +import {Utils} from "test/utils/Utils.sol"; import {IdentityUpdates} from "src/IdentityUpdates.sol"; +import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; import {Initializable} from "@openzeppelin-contracts-upgradeable/proxy/utils/Initializable.sol"; -import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; - -contract IdentityUpdatesTest is Test { - bytes32 constant DEFAULT_ADMIN_ROLE = 0x00; - bytes32 constant EIP1967_IMPL_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; - bytes32 constant INBOX_ID = 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef; +import {PausableUpgradeable} from "@openzeppelin-contracts-upgradeable/utils/PausableUpgradeable.sol"; +contract IdentityUpdatesTest is Test, IdentityUpdates, Utils { IdentityUpdates identityUpdatesImpl; ERC1967Proxy proxy; IdentityUpdates identityUpdates; @@ -24,32 +22,79 @@ contract IdentityUpdatesTest is Test { identityUpdatesImpl = new IdentityUpdates(); proxy = new ERC1967Proxy( - address(identityUpdatesImpl), - abi.encodeWithSelector(identityUpdates.initialize.selector, admin) + address(identityUpdatesImpl), abi.encodeWithSelector(identityUpdates.initialize.selector, admin) ); identityUpdates = IdentityUpdates(address(proxy)); } - function test_AddIdentityUpdateValid() public { - bytes memory message = new bytes(1024); - for (uint256 i = 0; i < message.length; i++) { - message[i] = bytes1(uint8(i % 256)); // Set each byte to its index modulo 256 - } + function testAddIdentityUpdateValid() public { + bytes memory message = _generatePayload(MIN_PAYLOAD_SIZE); + + vm.expectEmit(address(identityUpdates)); + emit IdentityUpdates.IdentityUpdateCreated(ID, message, 1); + + identityUpdates.addIdentityUpdate(ID, message); + } + + function testAddIdentityUpdateWithMaxPayload() public { + bytes memory message = _generatePayload(MAX_PAYLOAD_SIZE); vm.expectEmit(address(identityUpdates)); - emit IdentityUpdates.IdentityUpdateCreated(INBOX_ID, message, 1); - identityUpdates.addIdentityUpdate(INBOX_ID, message); + emit IdentityUpdates.IdentityUpdateCreated(ID, message, 1); + + identityUpdates.addIdentityUpdate(ID, message); + } + + function testAddIdentityUpdateTooSmall() public { + bytes memory message = _generatePayload(MIN_PAYLOAD_SIZE - 1); + + vm.expectRevert( + abi.encodeWithSelector( + IdentityUpdates.InvalidPayloadSize.selector, message.length, MIN_PAYLOAD_SIZE, MAX_PAYLOAD_SIZE + ) + ); + + identityUpdates.addIdentityUpdate(ID, message); } - function testAddMessageInvalid() public { - bytes memory message = new bytes(103); - for (uint256 i = 0; i < message.length; i++) { - message[i] = bytes1(uint8(i % 256)); - } + function testAddIdentityUpdateTooBig() public { + bytes memory message = _generatePayload(MAX_PAYLOAD_SIZE + 1); + + vm.expectRevert( + abi.encodeWithSelector( + IdentityUpdates.InvalidPayloadSize.selector, message.length, MIN_PAYLOAD_SIZE, MAX_PAYLOAD_SIZE + ) + ); - vm.expectRevert(IdentityUpdates.InvalidIdentityUpdate.selector); - identityUpdates.addIdentityUpdate(INBOX_ID, message); + identityUpdates.addIdentityUpdate(ID, message); + } + + function testAddIdentityUpdateWhenPaused() public { + bytes memory message = _generatePayload(MIN_PAYLOAD_SIZE); + + identityUpdates.pause(); + assertTrue(identityUpdates.paused()); + + vm.expectRevert(abi.encodeWithSelector(PausableUpgradeable.EnforcedPause.selector)); + + identityUpdates.addIdentityUpdate(ID, message); + } + + function testSequenceIdIncrement() public { + bytes memory message = _generatePayload(MIN_PAYLOAD_SIZE); + + vm.expectEmit(address(identityUpdates)); + emit IdentityUpdates.IdentityUpdateCreated(ID, message, 1); + identityUpdates.addIdentityUpdate(ID, message); + + vm.expectEmit(address(identityUpdates)); + emit IdentityUpdates.IdentityUpdateCreated(ID, message, 2); + identityUpdates.addIdentityUpdate(ID, message); + + vm.expectEmit(address(identityUpdates)); + emit IdentityUpdates.IdentityUpdateCreated(ID, message, 3); + identityUpdates.addIdentityUpdate(ID, message); } function testInvalidReinitialization() public { @@ -62,14 +107,22 @@ contract IdentityUpdatesTest is Test { assertTrue(identityUpdates.paused()); vm.prank(unauthorized); - vm.expectRevert(); + vm.expectRevert( + abi.encodeWithSelector( + IAccessControl.AccessControlUnauthorizedAccount.selector, unauthorized, DEFAULT_ADMIN_ROLE + ) + ); identityUpdates.unpause(); identityUpdates.unpause(); assertFalse(identityUpdates.paused()); vm.prank(unauthorized); - vm.expectRevert(); + vm.expectRevert( + abi.encodeWithSelector( + IAccessControl.AccessControlUnauthorizedAccount.selector, unauthorized, DEFAULT_ADMIN_ROLE + ) + ); identityUpdates.pause(); } @@ -84,11 +137,17 @@ contract IdentityUpdatesTest is Test { identityUpdates.revokeRole(DEFAULT_ADMIN_ROLE, unauthorized); vm.prank(unauthorized); - vm.expectRevert(revertRoleData(unauthorized)); + vm.expectRevert( + abi.encodeWithSelector( + IAccessControl.AccessControlUnauthorizedAccount.selector, unauthorized, DEFAULT_ADMIN_ROLE + ) + ); identityUpdates.pause(); identityUpdates.renounceRole(DEFAULT_ADMIN_ROLE, admin); - vm.expectRevert(revertRoleData(admin)); + vm.expectRevert( + abi.encodeWithSelector(IAccessControl.AccessControlUnauthorizedAccount.selector, admin, DEFAULT_ADMIN_ROLE) + ); identityUpdates.pause(); } @@ -96,11 +155,8 @@ contract IdentityUpdatesTest is Test { IdentityUpdates newIdentityUpdatesImpl = new IdentityUpdates(); address newImplAddress = address(newIdentityUpdatesImpl); address oldImplAddress = address(identityUpdatesImpl); - - bytes memory message = new bytes(104); - for (uint256 i = 0; i < message.length; i++) { - message[i] = bytes1(uint8(i % 256)); - } + + bytes memory message = _generatePayload(MIN_PAYLOAD_SIZE); // Retrieve the implementation address directly from the proxy storage. bytes32 rawImplAddress = vm.load(address(identityUpdates), EIP1967_IMPL_SLOT); @@ -109,12 +165,16 @@ contract IdentityUpdatesTest is Test { // Initialize sequenceId to 1. The state should be preserved between upgrades. vm.expectEmit(address(identityUpdates)); - emit IdentityUpdates.IdentityUpdateCreated(INBOX_ID, message, 1); - identityUpdates.addIdentityUpdate(INBOX_ID, message); + emit IdentityUpdates.IdentityUpdateCreated(ID, message, 1); + identityUpdates.addIdentityUpdate(ID, message); // Unauthorized upgrade attempts should revert. vm.prank(unauthorized); - vm.expectRevert(revertRoleData(unauthorized)); + vm.expectRevert( + abi.encodeWithSelector( + IAccessControl.AccessControlUnauthorizedAccount.selector, unauthorized, DEFAULT_ADMIN_ROLE + ) + ); identityUpdates.upgradeToAndCall(address(newIdentityUpdatesImpl), ""); // Authorized upgrade should succeed and emit UpgradeAuthorized event. @@ -129,11 +189,7 @@ contract IdentityUpdatesTest is Test { // Next sequenceId should be 2. vm.expectEmit(address(identityUpdates)); - emit IdentityUpdates.IdentityUpdateCreated(INBOX_ID, message, 2); - identityUpdates.addIdentityUpdate(INBOX_ID, message); - } - - function revertRoleData(address _user) public pure returns (bytes memory) { - return abi.encodeWithSelector(IAccessControl.AccessControlUnauthorizedAccount.selector, _user, DEFAULT_ADMIN_ROLE); + emit IdentityUpdates.IdentityUpdateCreated(ID, message, 2); + identityUpdates.addIdentityUpdate(ID, message); } } diff --git a/contracts/test/utils/Utils.sol b/contracts/test/utils/Utils.sol new file mode 100644 index 00000000..3382b31c --- /dev/null +++ b/contracts/test/utils/Utils.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.28; + +import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; +import {PausableUpgradeable} from "@openzeppelin-contracts-upgradeable/utils/PausableUpgradeable.sol"; + +contract Utils { + bytes32 public constant EIP1967_IMPL_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + bytes32 public constant ID = 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef; + + function _generatePayload(uint256 length) public pure returns (bytes memory) { + bytes memory payload = new bytes(length); + for (uint256 i = 0; i < payload.length; i++) { + payload[i] = bytes1(uint8(i % 256)); + } + return payload; + } +} diff --git a/dev/contracts/.env b/dev/contracts/.env index 96f170a8..226c91d8 100644 --- a/dev/contracts/.env +++ b/dev/contracts/.env @@ -1,3 +1,9 @@ # This is the first default private key for anvil. Nothing sensitive here. export PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 -export DOCKER_RPC_URL=http://localhost:7545 \ No newline at end of file +export DOCKER_RPC_URL=http://localhost:7545 + +### XMTP deployment configuration ### +# This is the address derivated from the private key above. Not sensitive. +export XMTP_GROUP_MESSAGES_ADMIN_ADDRESS=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 +export XMTP_IDENTITY_UPDATES_ADMIN_ADDRESS=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 +export XMTP_NODE_REGISTRY_ADMIN_ADDRESS=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 \ No newline at end of file diff --git a/dev/contracts/common b/dev/contracts/common new file mode 100644 index 00000000..a88be5a1 --- /dev/null +++ b/dev/contracts/common @@ -0,0 +1,41 @@ +#!/bin/bash +set -euo pipefail + +function forge_deploy_script() { + case $1 in + group_messages) + forge script --rpc-url "${DOCKER_RPC_URL}" --broadcast script/DeployGroupMessages.s.sol &> /dev/null + if [ $? -ne 0 ]; then + echo "Failed to deploy group messages contract" + exit 1 + fi + + echo -e "✅ GroupMessages contract deployed.\n" + cat script/output/31337/group_messages_deployment.json + echo -e "\n" + ;; + + identity_updates) + forge script --rpc-url "${DOCKER_RPC_URL}" --broadcast script/DeployIdentityUpdates.s.sol &> /dev/null + if [ $? -ne 0 ]; then + echo "Failed to deploy identity updates contract" + exit 1 + fi + + echo -e "✅ IdentityUpdates contract deployed.\n" + cat script/output/31337/identity_updates_deployment.json + echo -e "\n" + ;; + + *) + echo "Invalid option. Use 'group_messages' or 'identity_updates'." + exit 1 + ;; + esac +} + +# Deploy a contract and save the output (which includes the contract address) to a JSON file to be used in tests +# TODO: This should be a function in the forge CLI +function deploy_contract() { + forge create --broadcast --legacy --json --rpc-url $DOCKER_RPC_URL --private-key $PRIVATE_KEY "$1:$2" > ../build/$2.json +} diff --git a/dev/contracts/deploy-local b/dev/contracts/deploy-local index ce778651..6249f2c2 100755 --- a/dev/contracts/deploy-local +++ b/dev/contracts/deploy-local @@ -1,23 +1,24 @@ #!/bin/bash # Deploy the smart contracts to the local anvil node - set -euo pipefail - source dev/contracts/.env +source dev/contracts/common # Make sure the build directory exists mkdir -p ./build +# Move to working directory cd ./contracts # Update depencencies -forge soldeer install +forge soldeer update &> /dev/null +if [ $? -ne 0 ]; then + echo "ERROR: Failed to update dependencies" + exit 1 +fi -# Deploy a contract and save the output (which includes the contract address) to a JSON file to be used in tests -function deploy_contract() { - forge create --broadcast --legacy --json --rpc-url $DOCKER_RPC_URL --private-key $PRIVATE_KEY "$1:$2" > ../build/$2.json -} +forge_deploy_script group_messages +forge_deploy_script identity_updates -deploy_contract src/GroupMessages.sol GroupMessages +# TODO: This should be a function in the forge CLI deploy_contract src/Nodes.sol Nodes -deploy_contract src/IdentityUpdates.sol IdentityUpdates \ No newline at end of file diff --git a/dev/contracts/deploy-testnet b/dev/contracts/deploy-testnet index a0e98827..9e3c5ad0 100755 --- a/dev/contracts/deploy-testnet +++ b/dev/contracts/deploy-testnet @@ -23,4 +23,7 @@ function deploy_contract() { deploy_contract src/GroupMessages.sol GroupMessages deploy_contract src/Nodes.sol Nodes -deploy_contract src/IdentityUpdates.sol IdentityUpdates \ No newline at end of file +deploy_contract src/IdentityUpdates.sol IdentityUpdates + +# TODO: Migrate to forge script. +# TODO: Step to verify the deployed implementation and proxy. \ No newline at end of file diff --git a/dev/docker/up b/dev/docker/up index abc71a64..65949030 100755 --- a/dev/docker/up +++ b/dev/docker/up @@ -4,3 +4,4 @@ set -e docker_compose build docker_compose up -d --remove-orphans --wait +echo diff --git a/dev/up b/dev/up index 81a2f4a0..411df51a 100755 --- a/dev/up +++ b/dev/up @@ -16,6 +16,10 @@ if ! which abigen &>/dev/null; then go install github.com/ethereum/go-ethereum/c if ! which jq &>/dev/null; then brew install jq; fi dev/docker/up -dev/contracts/deploy-local +dev/contracts/deploy-local + +echo "Registering local node-1" dev/register-local-node + +echo "Registering local node-2" dev/register-local-node-2 \ No newline at end of file From 695aafd1f20f9d3c121fe659b70172e97541e256 Mon Sep 17 00:00:00 2001 From: Borja Aranda Date: Fri, 20 Dec 2024 13:47:15 +0100 Subject: [PATCH 5/8] make CI happy --- .../script/output/31337/GroupMessages.json | 10 ++++++ .../script/output/31337/IdentityUpdates.json | 10 ++++++ .../31337/group_messages_deployment.json | 10 ------ .../31337/identity_updates_deployment.json | 10 ------ contracts/script/utils/Environment.sol | 4 +-- dev/baked/Dockerfile | 4 +-- dev/contracts/common | 4 +-- dev/local.env | 9 ++++-- go.mod | 1 + go.sum | 2 ++ pkg/blockchain/blockchainPublisher_test.go | 2 +- pkg/testutils/config.go | 32 ++++++++++++++++--- 12 files changed, 64 insertions(+), 34 deletions(-) create mode 100644 contracts/script/output/31337/GroupMessages.json create mode 100644 contracts/script/output/31337/IdentityUpdates.json delete mode 100644 contracts/script/output/31337/group_messages_deployment.json delete mode 100644 contracts/script/output/31337/identity_updates_deployment.json diff --git a/contracts/script/output/31337/GroupMessages.json b/contracts/script/output/31337/GroupMessages.json new file mode 100644 index 00000000..0a15425f --- /dev/null +++ b/contracts/script/output/31337/GroupMessages.json @@ -0,0 +1,10 @@ +{ + "addresses": { + "groupMessagesDeployer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "groupMessagesImpl": "0xc0F115A19107322cFBf1cDBC7ea011C19EbDB4F8", + "groupMessagesProxy": "0xc96304e3c037f81dA488ed9dEa1D8F2a48278a75", + "groupMessagesProxyAdmin": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + }, + "deploymentBlock": 107, + "latestUpgradeBlock": 107 +} \ No newline at end of file diff --git a/contracts/script/output/31337/IdentityUpdates.json b/contracts/script/output/31337/IdentityUpdates.json new file mode 100644 index 00000000..ca52f0e1 --- /dev/null +++ b/contracts/script/output/31337/IdentityUpdates.json @@ -0,0 +1,10 @@ +{ + "addresses": { + "identityUpdatesDeployer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "identityUpdatesImpl": "0x34B40BA116d5Dec75548a9e9A8f15411461E8c70", + "identityUpdatesProxy": "0xD0141E899a65C95a556fE2B27e5982A6DE7fDD7A", + "identityUpdatesProxyAdmin": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + }, + "deploymentBlock": 109, + "latestUpgradeBlock": 109 +} \ No newline at end of file diff --git a/contracts/script/output/31337/group_messages_deployment.json b/contracts/script/output/31337/group_messages_deployment.json deleted file mode 100644 index d22c1632..00000000 --- a/contracts/script/output/31337/group_messages_deployment.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "addresses": { - "groupMessagesDeployer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "groupMessagesImpl": "0xe8D2A1E88c91DCd5433208d4152Cc4F399a7e91d", - "groupMessagesProxy": "0x5067457698Fd6Fa1C6964e416b3f42713513B3dD", - "groupMessagesProxyAdmin": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" - }, - "deploymentBlock": 100, - "latestUpgradeBlock": 100 -} \ No newline at end of file diff --git a/contracts/script/output/31337/identity_updates_deployment.json b/contracts/script/output/31337/identity_updates_deployment.json deleted file mode 100644 index 1ec61bc4..00000000 --- a/contracts/script/output/31337/identity_updates_deployment.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "addresses": { - "identityUpdatesDeployer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "identityUpdatesImpl": "0x18E317A7D70d8fBf8e6E893616b52390EbBdb629", - "identityUpdatesProxy": "0x4b6aB5F819A515382B0dEB6935D793817bB4af28", - "identityUpdatesProxyAdmin": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" - }, - "deploymentBlock": 102, - "latestUpgradeBlock": 102 -} \ No newline at end of file diff --git a/contracts/script/utils/Environment.sol b/contracts/script/utils/Environment.sol index 14ab89d4..1cc2a346 100644 --- a/contracts/script/utils/Environment.sol +++ b/contracts/script/utils/Environment.sol @@ -4,6 +4,6 @@ pragma solidity 0.8.28; import "forge-std/src/Script.sol"; contract Environment is Script { - string public constant XMTP_GROUP_MESSAGES_OUTPUT_JSON = "group_messages_deployment"; - string public constant XMTP_IDENTITY_UPDATES_OUTPUT_JSON = "identity_updates_deployment"; + string public constant XMTP_GROUP_MESSAGES_OUTPUT_JSON = "GroupMessages"; + string public constant XMTP_IDENTITY_UPDATES_OUTPUT_JSON = "IdentityUpdates"; } diff --git a/dev/baked/Dockerfile b/dev/baked/Dockerfile index ffe2de5d..06e75b9a 100644 --- a/dev/baked/Dockerfile +++ b/dev/baked/Dockerfile @@ -29,8 +29,8 @@ RUN dev/docker/anvil-background && \ sleep 5 RUN echo "export XMTPD_CONTRACTS_NODES_ADDRESS="$(jq -r '.deployedTo' build/Nodes.json)"" >> contracts.env && \ - echo "export XMTPD_CONTRACTS_MESSAGES_ADDRESS="$(jq -r '.deployedTo' build/GroupMessages.json)"" >> contracts.env && \ - echo "export XMTPD_CONTRACTS_IDENTITY_UPDATES_ADDRESS="$(jq -r '.deployedTo' build/IdentityUpdates.json)"" >> contracts.env + echo "export XMTPD_CONTRACTS_MESSAGES_ADDRESS="$(jq -r '.addresses.groupMessagesProxy' contracts/script/output/31337/GroupMessages.json)"" >> contracts.env && \ + echo "export XMTPD_CONTRACTS_IDENTITY_UPDATES_ADDRESS="$(jq -r '.addresses.identityUpdatesProxy' contracts/script/output/31337/IdentityUpdates.json)"" >> contracts.env # ACTUAL IMAGE ------------------------------------------------------- diff --git a/dev/contracts/common b/dev/contracts/common index a88be5a1..a8035b21 100644 --- a/dev/contracts/common +++ b/dev/contracts/common @@ -11,7 +11,7 @@ function forge_deploy_script() { fi echo -e "✅ GroupMessages contract deployed.\n" - cat script/output/31337/group_messages_deployment.json + cat script/output/31337/GroupMessages.json echo -e "\n" ;; @@ -23,7 +23,7 @@ function forge_deploy_script() { fi echo -e "✅ IdentityUpdates contract deployed.\n" - cat script/output/31337/identity_updates_deployment.json + cat script/output/31337/IdentityUpdates.json echo -e "\n" ;; diff --git a/dev/local.env b/dev/local.env index 482f2c3f..b934bddc 100755 --- a/dev/local.env +++ b/dev/local.env @@ -2,16 +2,19 @@ source dev/contracts/.env +# Anvil scripts output folder +ANVIL_SCRIPTS_OUTPUT=contracts/script/output/31337 + # DB Options export XMTPD_DB_WRITER_CONNECTION_STRING="postgres://postgres:xmtp@localhost:8765/postgres?sslmode=disable" # Contract Options export XMTPD_CONTRACTS_RPC_URL=$DOCKER_RPC_URL # From contracts/.env -XMTPD_CONTRACTS_NODES_ADDRESS="$(jq -r '.deployedTo' build/Nodes.json)" # Built by contracts/deploy-local +XMTPD_CONTRACTS_NODES_ADDRESS="$(jq -r '.deployedTo' build/Nodes.json)" # Built by contracts/deploy-local - TODO: move deployment to forge script export XMTPD_CONTRACTS_NODES_ADDRESS -XMTPD_CONTRACTS_MESSAGES_ADDRESS="$(jq -r '.deployedTo' build/GroupMessages.json)" # Built by contracts/deploy-local +XMTPD_CONTRACTS_MESSAGES_ADDRESS="$(jq -r '.addresses.groupMessagesProxy' ${ANVIL_SCRIPTS_OUTPUT}/GroupMessages.json)" # Built by contracts/deploy-local export XMTPD_CONTRACTS_MESSAGES_ADDRESS -XMTPD_CONTRACTS_IDENTITY_UPDATES_ADDRESS="$(jq -r '.deployedTo' build/IdentityUpdates.json)" # Built by contracts/deploy-local +XMTPD_CONTRACTS_IDENTITY_UPDATES_ADDRESS="$(jq -r '.addresses.identityUpdatesProxy' ${ANVIL_SCRIPTS_OUTPUT}/IdentityUpdates.json)" # Built by contracts/deploy-local export XMTPD_CONTRACTS_IDENTITY_UPDATES_ADDRESS export ANVIL_ACC_1_PRIVATE_KEY="0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d" diff --git a/go.mod b/go.mod index 8de162ae..fbec9ffe 100644 --- a/go.mod +++ b/go.mod @@ -29,6 +29,7 @@ require ( require ( github.com/golang-jwt/jwt/v5 v5.2.1 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 + github.com/valyala/fastjson v1.6.4 ) require ( diff --git a/go.sum b/go.sum index 6d9f6939..9ca86d01 100644 --- a/go.sum +++ b/go.sum @@ -1153,6 +1153,8 @@ github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3C github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ= +github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/vbatts/tar-split v0.11.6 h1:4SjTW5+PU11n6fZenf2IPoV8/tz3AaYHMWjf23envGs= diff --git a/pkg/blockchain/blockchainPublisher_test.go b/pkg/blockchain/blockchainPublisher_test.go index aee4e0b1..36bd99e2 100644 --- a/pkg/blockchain/blockchainPublisher_test.go +++ b/pkg/blockchain/blockchainPublisher_test.go @@ -47,7 +47,7 @@ func TestPublishIdentityUpdate(t *testing.T) { { name: "happy path", inboxId: testutils.RandomGroupID(), - identityUpdate: testutils.RandomBytes(100), + identityUpdate: testutils.RandomBytes(104), ctx: context.Background(), wantErr: false, }, diff --git a/pkg/testutils/config.go b/pkg/testutils/config.go index 0f7c456d..42eccff8 100644 --- a/pkg/testutils/config.go +++ b/pkg/testutils/config.go @@ -5,10 +5,12 @@ import ( "os" "path" "path/filepath" + "strings" "testing" "time" "github.com/stretchr/testify/require" + "github.com/valyala/fastjson" "github.com/xmtp/xmtpd/pkg/config" ) @@ -48,6 +50,7 @@ func rootPath(t *testing.T) string { /* * Parse the JSON file at this location to get the deployed contract info +TODO: deprecate in favor of getProxyAddress * */ func getDeployedTo(t *testing.T, fileName string) string { @@ -65,19 +68,40 @@ func getDeployedTo(t *testing.T, fileName string) string { return info.DeployedTo } +/* +* +Parse the JSON file at this location to get the deployed contract proxy address +* +*/ +func getProxyAddress(t *testing.T, fileName string) string { + data, err := os.ReadFile(fileName) + if err != nil { + t.Fatalf("Failed to read json: %v", err) + } + + switch { + case strings.Contains(fileName, "GroupMessages.json"): + return fastjson.GetString(data, "addresses", "groupMessagesProxy") + case strings.Contains(fileName, "IdentityUpdates.json"): + return fastjson.GetString(data, "addresses", "identityUpdatesProxy") + default: + return "" + } +} + func GetContractsOptions(t *testing.T) config.ContractsOptions { rootDir := rootPath(t) return config.ContractsOptions{ RpcUrl: BLOCKCHAIN_RPC_URL, - MessagesContractAddress: getDeployedTo( + MessagesContractAddress: getProxyAddress( t, - path.Join(rootDir, "./build/GroupMessages.json"), + path.Join(rootDir, "./contracts/script/output/31337/GroupMessages.json"), ), NodesContractAddress: getDeployedTo(t, path.Join(rootDir, "./build/Nodes.json")), - IdentityUpdatesContractAddress: getDeployedTo( + IdentityUpdatesContractAddress: getProxyAddress( t, - path.Join(rootDir, "./build/IdentityUpdates.json"), + path.Join(rootDir, "./contracts/script/output/31337/IdentityUpdates.json"), ), RefreshInterval: 100 * time.Millisecond, ChainID: 31337, From 9b178c9cd102855265d8337e5c7cf4ac45f8d873 Mon Sep 17 00:00:00 2001 From: Borja Aranda Date: Fri, 20 Dec 2024 14:57:44 +0100 Subject: [PATCH 6/8] move contract dev scripts to dev/contracts --- .gitignore | 3 + .../script/output/31337/GroupMessages.json | 8 +- .../script/output/31337/IdentityUpdates.json | 8 +- dev/abigen | 20 - dev/contracts/generate | 25 + dev/generate | 2 +- dev/up | 3 + pkg/abis/groupMessages.go | 1677 ++++++++++++++++- pkg/abis/identityUpdates.go | 1617 +++++++++++++++- pkg/abis/nodes.go | 22 + pkg/indexer/e2e_test.go | 2 +- 11 files changed, 3325 insertions(+), 62 deletions(-) delete mode 100755 dev/abigen create mode 100755 dev/contracts/generate diff --git a/.gitignore b/.gitignore index c10451f4..b49e3161 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,9 @@ *.so *.dylib +# delve debugger +__debug_* + # build folder build/ bin/ diff --git a/contracts/script/output/31337/GroupMessages.json b/contracts/script/output/31337/GroupMessages.json index 0a15425f..d20f6cc2 100644 --- a/contracts/script/output/31337/GroupMessages.json +++ b/contracts/script/output/31337/GroupMessages.json @@ -1,10 +1,10 @@ { "addresses": { "groupMessagesDeployer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "groupMessagesImpl": "0xc0F115A19107322cFBf1cDBC7ea011C19EbDB4F8", - "groupMessagesProxy": "0xc96304e3c037f81dA488ed9dEa1D8F2a48278a75", + "groupMessagesImpl": "0xB0f05d25e41FbC2b52013099ED9616f1206Ae21B", + "groupMessagesProxy": "0x5FeaeBfB4439F3516c74939A9D04e95AFE82C4ae", "groupMessagesProxyAdmin": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" }, - "deploymentBlock": 107, - "latestUpgradeBlock": 107 + "deploymentBlock": 43, + "latestUpgradeBlock": 43 } \ No newline at end of file diff --git a/contracts/script/output/31337/IdentityUpdates.json b/contracts/script/output/31337/IdentityUpdates.json index ca52f0e1..cd8f4b2a 100644 --- a/contracts/script/output/31337/IdentityUpdates.json +++ b/contracts/script/output/31337/IdentityUpdates.json @@ -1,10 +1,10 @@ { "addresses": { "identityUpdatesDeployer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "identityUpdatesImpl": "0x34B40BA116d5Dec75548a9e9A8f15411461E8c70", - "identityUpdatesProxy": "0xD0141E899a65C95a556fE2B27e5982A6DE7fDD7A", + "identityUpdatesImpl": "0x976fcd02f7C4773dd89C309fBF55D5923B4c98a1", + "identityUpdatesProxy": "0x19cEcCd6942ad38562Ee10bAfd44776ceB67e923", "identityUpdatesProxyAdmin": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" }, - "deploymentBlock": 109, - "latestUpgradeBlock": 109 + "deploymentBlock": 45, + "latestUpgradeBlock": 45 } \ No newline at end of file diff --git a/dev/abigen b/dev/abigen deleted file mode 100755 index 8f07a721..00000000 --- a/dev/abigen +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -set -e - -rm -f ./build/*.abi.json -rm -f ./pkg/abis/*.go - -cd contracts - -# Generate the abi files out of the solidity code -mkdir -p ../build -forge inspect ./src/Nodes.sol:Nodes abi > ../build/Nodes.abi.json -forge inspect ./src/GroupMessages.sol:GroupMessages abi > ../build/GroupMessages.abi.json -forge inspect ./src/IdentityUpdates.sol:IdentityUpdates abi > ../build/IdentityUpdates.abi.json - -cd .. -# Generate Go code out of the ABI files -abigen --abi ./build/Nodes.abi.json --pkg abis --type Nodes --out ./pkg/abis/nodes.go -abigen --abi ./build/GroupMessages.abi.json --pkg abis --type GroupMessages --out ./pkg/abis/groupMessages.go -abigen --abi ./build/IdentityUpdates.abi.json --pkg abis --type IdentityUpdates --out ./pkg/abis/identityUpdates.go \ No newline at end of file diff --git a/dev/contracts/generate b/dev/contracts/generate new file mode 100755 index 00000000..9031c821 --- /dev/null +++ b/dev/contracts/generate @@ -0,0 +1,25 @@ +#!/bin/bash + +set -e + +PACKAGE_NAME="abis" +BUILD_DIR="build" +OUTPUT_DIR="pkg/abis" + +mkdir -p ./build +rm -f ./build/*.abi.json +rm -f ./pkg/abis/*.go + +function generate_bindings() { + cd contracts + forge inspect ./src/${1}.sol:${1} abi > ../${BUILD_DIR}/${1}.abi.json + forge inspect ./src/${1}.sol:${1} bytecode > ../${BUILD_DIR}/${1}.bin.json + + cd .. + abigen --abi ./${BUILD_DIR}/${1}.abi.json --bin ./${BUILD_DIR}/${1}.bin.json --pkg "${PACKAGE_NAME}" --type "${1}" --out "./${OUTPUT_DIR}/${1}.go" > /dev/null 2>&1 + +} + +for contract in Nodes GroupMessages IdentityUpdates; do + generate_bindings $contract +done diff --git a/dev/generate b/dev/generate index 5f7b60eb..8de689de 100755 --- a/dev/generate +++ b/dev/generate @@ -6,5 +6,5 @@ set -euo pipefail sqlc generate go generate ./... rm -rf pkg/mocks/* -./dev/abigen +./dev/contracts/generate mockery diff --git a/dev/up b/dev/up index 411df51a..a82997f5 100755 --- a/dev/up +++ b/dev/up @@ -16,6 +16,9 @@ if ! which abigen &>/dev/null; then go install github.com/ethereum/go-ethereum/c if ! which jq &>/dev/null; then brew install jq; fi dev/docker/up + +# Make sure the abis are updated +dev/contracts/generate dev/contracts/deploy-local echo "Registering local node-1" diff --git a/pkg/abis/groupMessages.go b/pkg/abis/groupMessages.go index eff273f0..47355324 100644 --- a/pkg/abis/groupMessages.go +++ b/pkg/abis/groupMessages.go @@ -31,13 +31,35 @@ var ( // GroupMessagesMetaData contains all meta data concerning the GroupMessages contract. var GroupMessagesMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"function\",\"name\":\"addMessage\",\"inputs\":[{\"name\":\"groupId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"message\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"MessageSent\",\"inputs\":[{\"name\":\"groupId\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"message\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"sequenceId\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false}]", + ABI: "[{\"type\":\"function\",\"name\":\"DEFAULT_ADMIN_ROLE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MAX_PAYLOAD_SIZE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MIN_PAYLOAD_SIZE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"UPGRADE_INTERFACE_VERSION\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"addMessage\",\"inputs\":[{\"name\":\"groupId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"message\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getRoleAdmin\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"grantRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"hasRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"_admin\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"pause\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"paused\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proxiableUUID\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"renounceRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"callerConfirmation\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"revokeRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"unpause\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"inputs\":[{\"name\":\"newImplementation\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"MessageSent\",\"inputs\":[{\"name\":\"groupId\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"message\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"sequenceId\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Paused\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleAdminChanged\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"previousAdminRole\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"newAdminRole\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleGranted\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleRevoked\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Unpaused\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"UpgradeAuthorized\",\"inputs\":[{\"name\":\"upgrader\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"newImplementation\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Upgraded\",\"inputs\":[{\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AccessControlBadConfirmation\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AccessControlUnauthorizedAccount\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"neededRole\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"AddressEmptyCode\",\"inputs\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ERC1967InvalidImplementation\",\"inputs\":[{\"name\":\"implementation\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ERC1967NonPayable\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"EnforcedPause\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ExpectedPause\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"FailedCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidPayloadSize\",\"inputs\":[{\"name\":\"actualSize\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"minSize\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"maxSize\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UUPSUnauthorizedCallContext\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UUPSUnsupportedProxiableUUID\",\"inputs\":[{\"name\":\"slot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"ZeroAdminAddress\",\"inputs\":[]}]", + Bin: "0x60a0604052306080523480156012575f5ffd5b506080516117be6100395f395f8181610ba401528181610bcd0152610ee001526117be5ff3fe608060405260043610610109575f3560e01c80635c975abb116100a1578063a2ba193411610071578063c4d66de811610057578063c4d66de81461036e578063d547741f1461038d578063f5368506146103ac575f5ffd5b8063a2ba193414610303578063ad3cb1cc14610319575f5ffd5b80635c975abb146102365780638456cb591461026c57806391d1485414610280578063a217fddf146102f0575f5ffd5b80633f4ba83a116100dc5780633f4ba83a146101dc5780634dff26b5146101f05780634f1ef2861461020f57806352d1902d14610222575f5ffd5b806301ffc9a71461010d578063248a9ca3146101415780632f2ff15d1461019c57806336568abe146101bd575b5f5ffd5b348015610118575f5ffd5b5061012c61012736600461143c565b6103c0565b60405190151581526020015b60405180910390f35b34801561014c575f5ffd5b5061018e61015b36600461147b565b5f9081527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052604090206001015490565b604051908152602001610138565b3480156101a7575f5ffd5b506101bb6101b63660046114ba565b610458565b005b3480156101c8575f5ffd5b506101bb6101d73660046114ba565b6104a1565b3480156101e7575f5ffd5b506101bb6104ff565b3480156101fb575f5ffd5b506101bb61020a3660046114e4565b610514565b6101bb61021d366004611588565b610606565b34801561022d575f5ffd5b5061018e610625565b348015610241575f5ffd5b507fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff1661012c565b348015610277575f5ffd5b506101bb610653565b34801561028b575f5ffd5b5061012c61029a3660046114ba565b5f9182527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020908152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b3480156102fb575f5ffd5b5061018e5f81565b34801561030e575f5ffd5b5061018e6240000081565b348015610324575f5ffd5b506103616040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101389190611689565b348015610379575f5ffd5b506101bb6103883660046116dc565b610665565b348015610398575f5ffd5b506101bb6103a73660046114ba565b61084a565b3480156103b7575f5ffd5b5061018e604e81565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061045257507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260409020600101546104918161088d565b61049b8383610897565b50505050565b73ffffffffffffffffffffffffffffffffffffffff811633146104f0576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104fa82826109b5565b505050565b5f6105098161088d565b610511610a91565b50565b61051c610b2e565b604e81108015906105305750624000008111155b8190604e906240000090610586576040517f93b7abe60000000000000000000000000000000000000000000000000000000081526004810193909352602483019190915260448201526064015b60405180910390fd5b50505f805467ffffffffffffffff808216600101167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090911681179091556040517f91f47151424884a46811ed593aa8a02ee5012e9332a4dcf1e9236a8ed4443c3e92506105f9918691869186916116f5565b60405180910390a1505050565b61060e610b8c565b61061782610c90565b6106218282610d8f565b5050565b5f61062e610ec8565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b5f61065d8161088d565b610511610f37565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f811580156106af5750825b90505f8267ffffffffffffffff1660011480156106cb5750303b155b9050811580156106d9575080155b15610710576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117855583156107715784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b73ffffffffffffffffffffffffffffffffffffffff86166107be576040517f3ef39b8100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107c6610fb0565b6107ce610fb0565b6107d6610fb8565b6107e05f87610897565b5083156108425784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260409020600101546108838161088d565b61049b83836109b5565b6105118133610fc8565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020818152604080842073ffffffffffffffffffffffffffffffffffffffff8616855290915282205460ff166109ac575f8481526020828152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556109483390565b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a46001915050610452565b5f915050610452565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020818152604080842073ffffffffffffffffffffffffffffffffffffffff8616855290915282205460ff16156109ac575f8481526020828152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a46001915050610452565b610a9961106e565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001681557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a150565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff1615610b8a576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b3073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480610c5957507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16610c407f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614155b15610b8a576040517fe07c8dba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f610c9a8161088d565b73ffffffffffffffffffffffffffffffffffffffff8216610d3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4e657720696d706c656d656e746174696f6e2063616e6e6f74206265207a657260448201527f6f20616464726573730000000000000000000000000000000000000000000000606482015260840161057d565b6040805133815273ffffffffffffffffffffffffffffffffffffffff841660208201527fd30e1d298bf814ea43d22b4ce8298062b08609cd67496483769d836157dd52fa910160405180910390a15050565b8173ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610e14575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252610e119181019061175b565b60015b610e62576040517f4c9c8ce300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015260240161057d565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114610ebe576040517faa1d49a40000000000000000000000000000000000000000000000000000000081526004810182905260240161057d565b6104fa83836110c9565b3073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610b8a576040517fe07c8dba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f3f610b2e565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011781557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25833610b03565b610b8a61112b565b610fc061112b565b610b8a611192565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16610621576040517fe2517d3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024810183905260440161057d565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff16610b8a576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110d2826111e3565b60405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115611123576104fa82826112b1565b610621611330565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff16610b8a576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61119a61112b565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b8073ffffffffffffffffffffffffffffffffffffffff163b5f0361124b576040517f4c9c8ce300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260240161057d565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60605f5f8473ffffffffffffffffffffffffffffffffffffffff16846040516112da9190611772565b5f60405180830381855af49150503d805f8114611312576040519150601f19603f3d011682016040523d82523d5f602084013e611317565b606091505b5091509150611327858383611368565b95945050505050565b3415610b8a576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608261137d57611378826113fa565b6113f3565b81511580156113a1575073ffffffffffffffffffffffffffffffffffffffff84163b155b156113f0576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015260240161057d565b50805b9392505050565b80511561140a5780518082602001fd5b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6020828403121561144c575f5ffd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146113f3575f5ffd5b5f6020828403121561148b575f5ffd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff811681146114b5575f5ffd5b919050565b5f5f604083850312156114cb575f5ffd5b823591506114db60208401611492565b90509250929050565b5f5f5f604084860312156114f6575f5ffd5b83359250602084013567ffffffffffffffff811115611513575f5ffd5b8401601f81018613611523575f5ffd5b803567ffffffffffffffff811115611539575f5ffd5b86602082840101111561154a575f5ffd5b939660209190910195509293505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f5f60408385031215611599575f5ffd5b6115a283611492565b9150602083013567ffffffffffffffff8111156115bd575f5ffd5b8301601f810185136115cd575f5ffd5b803567ffffffffffffffff8111156115e7576115e761155b565b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8501160116810181811067ffffffffffffffff821117156116535761165361155b565b60405281815282820160200187101561166a575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b5f602082840312156116ec575f5ffd5b6113f382611492565b84815260606020820152826060820152828460808301375f608084830101525f60807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116830101905067ffffffffffffffff8316604083015295945050505050565b5f6020828403121561176b575f5ffd5b5051919050565b5f82518060208501845e5f92019182525091905056fea264697066735822122072d7566503253678adc66fd27920aaabe0ac779b70ca5ff95eb4b05309ab3a9064736f6c634300081c0033", } // GroupMessagesABI is the input ABI used to generate the binding from. // Deprecated: Use GroupMessagesMetaData.ABI instead. var GroupMessagesABI = GroupMessagesMetaData.ABI +// GroupMessagesBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use GroupMessagesMetaData.Bin instead. +var GroupMessagesBin = GroupMessagesMetaData.Bin + +// DeployGroupMessages deploys a new Ethereum contract, binding an instance of GroupMessages to it. +func DeployGroupMessages(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *GroupMessages, error) { + parsed, err := GroupMessagesMetaData.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(GroupMessagesBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &GroupMessages{GroupMessagesCaller: GroupMessagesCaller{contract: contract}, GroupMessagesTransactor: GroupMessagesTransactor{contract: contract}, GroupMessagesFilterer: GroupMessagesFilterer{contract: contract}}, nil +} + // GroupMessages is an auto generated Go binding around an Ethereum contract. type GroupMessages struct { GroupMessagesCaller // Read-only binding to the contract @@ -180,6 +202,285 @@ func (_GroupMessages *GroupMessagesTransactorRaw) Transact(opts *bind.TransactOp return _GroupMessages.Contract.contract.Transact(opts, method, params...) } +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_GroupMessages *GroupMessagesCaller) DEFAULTADMINROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _GroupMessages.contract.Call(opts, &out, "DEFAULT_ADMIN_ROLE") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_GroupMessages *GroupMessagesSession) DEFAULTADMINROLE() ([32]byte, error) { + return _GroupMessages.Contract.DEFAULTADMINROLE(&_GroupMessages.CallOpts) +} + +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_GroupMessages *GroupMessagesCallerSession) DEFAULTADMINROLE() ([32]byte, error) { + return _GroupMessages.Contract.DEFAULTADMINROLE(&_GroupMessages.CallOpts) +} + +// MAXPAYLOADSIZE is a free data retrieval call binding the contract method 0xa2ba1934. +// +// Solidity: function MAX_PAYLOAD_SIZE() view returns(uint256) +func (_GroupMessages *GroupMessagesCaller) MAXPAYLOADSIZE(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _GroupMessages.contract.Call(opts, &out, "MAX_PAYLOAD_SIZE") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// MAXPAYLOADSIZE is a free data retrieval call binding the contract method 0xa2ba1934. +// +// Solidity: function MAX_PAYLOAD_SIZE() view returns(uint256) +func (_GroupMessages *GroupMessagesSession) MAXPAYLOADSIZE() (*big.Int, error) { + return _GroupMessages.Contract.MAXPAYLOADSIZE(&_GroupMessages.CallOpts) +} + +// MAXPAYLOADSIZE is a free data retrieval call binding the contract method 0xa2ba1934. +// +// Solidity: function MAX_PAYLOAD_SIZE() view returns(uint256) +func (_GroupMessages *GroupMessagesCallerSession) MAXPAYLOADSIZE() (*big.Int, error) { + return _GroupMessages.Contract.MAXPAYLOADSIZE(&_GroupMessages.CallOpts) +} + +// MINPAYLOADSIZE is a free data retrieval call binding the contract method 0xf5368506. +// +// Solidity: function MIN_PAYLOAD_SIZE() view returns(uint256) +func (_GroupMessages *GroupMessagesCaller) MINPAYLOADSIZE(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _GroupMessages.contract.Call(opts, &out, "MIN_PAYLOAD_SIZE") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// MINPAYLOADSIZE is a free data retrieval call binding the contract method 0xf5368506. +// +// Solidity: function MIN_PAYLOAD_SIZE() view returns(uint256) +func (_GroupMessages *GroupMessagesSession) MINPAYLOADSIZE() (*big.Int, error) { + return _GroupMessages.Contract.MINPAYLOADSIZE(&_GroupMessages.CallOpts) +} + +// MINPAYLOADSIZE is a free data retrieval call binding the contract method 0xf5368506. +// +// Solidity: function MIN_PAYLOAD_SIZE() view returns(uint256) +func (_GroupMessages *GroupMessagesCallerSession) MINPAYLOADSIZE() (*big.Int, error) { + return _GroupMessages.Contract.MINPAYLOADSIZE(&_GroupMessages.CallOpts) +} + +// UPGRADEINTERFACEVERSION is a free data retrieval call binding the contract method 0xad3cb1cc. +// +// Solidity: function UPGRADE_INTERFACE_VERSION() view returns(string) +func (_GroupMessages *GroupMessagesCaller) UPGRADEINTERFACEVERSION(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _GroupMessages.contract.Call(opts, &out, "UPGRADE_INTERFACE_VERSION") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// UPGRADEINTERFACEVERSION is a free data retrieval call binding the contract method 0xad3cb1cc. +// +// Solidity: function UPGRADE_INTERFACE_VERSION() view returns(string) +func (_GroupMessages *GroupMessagesSession) UPGRADEINTERFACEVERSION() (string, error) { + return _GroupMessages.Contract.UPGRADEINTERFACEVERSION(&_GroupMessages.CallOpts) +} + +// UPGRADEINTERFACEVERSION is a free data retrieval call binding the contract method 0xad3cb1cc. +// +// Solidity: function UPGRADE_INTERFACE_VERSION() view returns(string) +func (_GroupMessages *GroupMessagesCallerSession) UPGRADEINTERFACEVERSION() (string, error) { + return _GroupMessages.Contract.UPGRADEINTERFACEVERSION(&_GroupMessages.CallOpts) +} + +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_GroupMessages *GroupMessagesCaller) GetRoleAdmin(opts *bind.CallOpts, role [32]byte) ([32]byte, error) { + var out []interface{} + err := _GroupMessages.contract.Call(opts, &out, "getRoleAdmin", role) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_GroupMessages *GroupMessagesSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _GroupMessages.Contract.GetRoleAdmin(&_GroupMessages.CallOpts, role) +} + +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_GroupMessages *GroupMessagesCallerSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _GroupMessages.Contract.GetRoleAdmin(&_GroupMessages.CallOpts, role) +} + +// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_GroupMessages *GroupMessagesCaller) HasRole(opts *bind.CallOpts, role [32]byte, account common.Address) (bool, error) { + var out []interface{} + err := _GroupMessages.contract.Call(opts, &out, "hasRole", role, account) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_GroupMessages *GroupMessagesSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _GroupMessages.Contract.HasRole(&_GroupMessages.CallOpts, role, account) +} + +// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_GroupMessages *GroupMessagesCallerSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _GroupMessages.Contract.HasRole(&_GroupMessages.CallOpts, role, account) +} + +// Paused is a free data retrieval call binding the contract method 0x5c975abb. +// +// Solidity: function paused() view returns(bool) +func (_GroupMessages *GroupMessagesCaller) Paused(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _GroupMessages.contract.Call(opts, &out, "paused") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// Paused is a free data retrieval call binding the contract method 0x5c975abb. +// +// Solidity: function paused() view returns(bool) +func (_GroupMessages *GroupMessagesSession) Paused() (bool, error) { + return _GroupMessages.Contract.Paused(&_GroupMessages.CallOpts) +} + +// Paused is a free data retrieval call binding the contract method 0x5c975abb. +// +// Solidity: function paused() view returns(bool) +func (_GroupMessages *GroupMessagesCallerSession) Paused() (bool, error) { + return _GroupMessages.Contract.Paused(&_GroupMessages.CallOpts) +} + +// ProxiableUUID is a free data retrieval call binding the contract method 0x52d1902d. +// +// Solidity: function proxiableUUID() view returns(bytes32) +func (_GroupMessages *GroupMessagesCaller) ProxiableUUID(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _GroupMessages.contract.Call(opts, &out, "proxiableUUID") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// ProxiableUUID is a free data retrieval call binding the contract method 0x52d1902d. +// +// Solidity: function proxiableUUID() view returns(bytes32) +func (_GroupMessages *GroupMessagesSession) ProxiableUUID() ([32]byte, error) { + return _GroupMessages.Contract.ProxiableUUID(&_GroupMessages.CallOpts) +} + +// ProxiableUUID is a free data retrieval call binding the contract method 0x52d1902d. +// +// Solidity: function proxiableUUID() view returns(bytes32) +func (_GroupMessages *GroupMessagesCallerSession) ProxiableUUID() ([32]byte, error) { + return _GroupMessages.Contract.ProxiableUUID(&_GroupMessages.CallOpts) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_GroupMessages *GroupMessagesCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _GroupMessages.contract.Call(opts, &out, "supportsInterface", interfaceId) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_GroupMessages *GroupMessagesSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _GroupMessages.Contract.SupportsInterface(&_GroupMessages.CallOpts, interfaceId) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_GroupMessages *GroupMessagesCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _GroupMessages.Contract.SupportsInterface(&_GroupMessages.CallOpts, interfaceId) +} + // AddMessage is a paid mutator transaction binding the contract method 0x4dff26b5. // // Solidity: function addMessage(bytes32 groupId, bytes message) returns() @@ -201,9 +502,156 @@ func (_GroupMessages *GroupMessagesTransactorSession) AddMessage(groupId [32]byt return _GroupMessages.Contract.AddMessage(&_GroupMessages.TransactOpts, groupId, message) } -// GroupMessagesMessageSentIterator is returned from FilterMessageSent and is used to iterate over the raw logs and unpacked data for MessageSent events raised by the GroupMessages contract. -type GroupMessagesMessageSentIterator struct { - Event *GroupMessagesMessageSent // Event containing the contract specifics and raw log +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_GroupMessages *GroupMessagesTransactor) GrantRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _GroupMessages.contract.Transact(opts, "grantRole", role, account) +} + +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_GroupMessages *GroupMessagesSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _GroupMessages.Contract.GrantRole(&_GroupMessages.TransactOpts, role, account) +} + +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_GroupMessages *GroupMessagesTransactorSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _GroupMessages.Contract.GrantRole(&_GroupMessages.TransactOpts, role, account) +} + +// Initialize is a paid mutator transaction binding the contract method 0xc4d66de8. +// +// Solidity: function initialize(address _admin) returns() +func (_GroupMessages *GroupMessagesTransactor) Initialize(opts *bind.TransactOpts, _admin common.Address) (*types.Transaction, error) { + return _GroupMessages.contract.Transact(opts, "initialize", _admin) +} + +// Initialize is a paid mutator transaction binding the contract method 0xc4d66de8. +// +// Solidity: function initialize(address _admin) returns() +func (_GroupMessages *GroupMessagesSession) Initialize(_admin common.Address) (*types.Transaction, error) { + return _GroupMessages.Contract.Initialize(&_GroupMessages.TransactOpts, _admin) +} + +// Initialize is a paid mutator transaction binding the contract method 0xc4d66de8. +// +// Solidity: function initialize(address _admin) returns() +func (_GroupMessages *GroupMessagesTransactorSession) Initialize(_admin common.Address) (*types.Transaction, error) { + return _GroupMessages.Contract.Initialize(&_GroupMessages.TransactOpts, _admin) +} + +// Pause is a paid mutator transaction binding the contract method 0x8456cb59. +// +// Solidity: function pause() returns() +func (_GroupMessages *GroupMessagesTransactor) Pause(opts *bind.TransactOpts) (*types.Transaction, error) { + return _GroupMessages.contract.Transact(opts, "pause") +} + +// Pause is a paid mutator transaction binding the contract method 0x8456cb59. +// +// Solidity: function pause() returns() +func (_GroupMessages *GroupMessagesSession) Pause() (*types.Transaction, error) { + return _GroupMessages.Contract.Pause(&_GroupMessages.TransactOpts) +} + +// Pause is a paid mutator transaction binding the contract method 0x8456cb59. +// +// Solidity: function pause() returns() +func (_GroupMessages *GroupMessagesTransactorSession) Pause() (*types.Transaction, error) { + return _GroupMessages.Contract.Pause(&_GroupMessages.TransactOpts) +} + +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_GroupMessages *GroupMessagesTransactor) RenounceRole(opts *bind.TransactOpts, role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _GroupMessages.contract.Transact(opts, "renounceRole", role, callerConfirmation) +} + +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_GroupMessages *GroupMessagesSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _GroupMessages.Contract.RenounceRole(&_GroupMessages.TransactOpts, role, callerConfirmation) +} + +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_GroupMessages *GroupMessagesTransactorSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _GroupMessages.Contract.RenounceRole(&_GroupMessages.TransactOpts, role, callerConfirmation) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_GroupMessages *GroupMessagesTransactor) RevokeRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _GroupMessages.contract.Transact(opts, "revokeRole", role, account) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_GroupMessages *GroupMessagesSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _GroupMessages.Contract.RevokeRole(&_GroupMessages.TransactOpts, role, account) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_GroupMessages *GroupMessagesTransactorSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _GroupMessages.Contract.RevokeRole(&_GroupMessages.TransactOpts, role, account) +} + +// Unpause is a paid mutator transaction binding the contract method 0x3f4ba83a. +// +// Solidity: function unpause() returns() +func (_GroupMessages *GroupMessagesTransactor) Unpause(opts *bind.TransactOpts) (*types.Transaction, error) { + return _GroupMessages.contract.Transact(opts, "unpause") +} + +// Unpause is a paid mutator transaction binding the contract method 0x3f4ba83a. +// +// Solidity: function unpause() returns() +func (_GroupMessages *GroupMessagesSession) Unpause() (*types.Transaction, error) { + return _GroupMessages.Contract.Unpause(&_GroupMessages.TransactOpts) +} + +// Unpause is a paid mutator transaction binding the contract method 0x3f4ba83a. +// +// Solidity: function unpause() returns() +func (_GroupMessages *GroupMessagesTransactorSession) Unpause() (*types.Transaction, error) { + return _GroupMessages.Contract.Unpause(&_GroupMessages.TransactOpts) +} + +// UpgradeToAndCall is a paid mutator transaction binding the contract method 0x4f1ef286. +// +// Solidity: function upgradeToAndCall(address newImplementation, bytes data) payable returns() +func (_GroupMessages *GroupMessagesTransactor) UpgradeToAndCall(opts *bind.TransactOpts, newImplementation common.Address, data []byte) (*types.Transaction, error) { + return _GroupMessages.contract.Transact(opts, "upgradeToAndCall", newImplementation, data) +} + +// UpgradeToAndCall is a paid mutator transaction binding the contract method 0x4f1ef286. +// +// Solidity: function upgradeToAndCall(address newImplementation, bytes data) payable returns() +func (_GroupMessages *GroupMessagesSession) UpgradeToAndCall(newImplementation common.Address, data []byte) (*types.Transaction, error) { + return _GroupMessages.Contract.UpgradeToAndCall(&_GroupMessages.TransactOpts, newImplementation, data) +} + +// UpgradeToAndCall is a paid mutator transaction binding the contract method 0x4f1ef286. +// +// Solidity: function upgradeToAndCall(address newImplementation, bytes data) payable returns() +func (_GroupMessages *GroupMessagesTransactorSession) UpgradeToAndCall(newImplementation common.Address, data []byte) (*types.Transaction, error) { + return _GroupMessages.Contract.UpgradeToAndCall(&_GroupMessages.TransactOpts, newImplementation, data) +} + +// GroupMessagesInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the GroupMessages contract. +type GroupMessagesInitializedIterator struct { + Event *GroupMessagesInitialized // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -217,7 +665,7 @@ type GroupMessagesMessageSentIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *GroupMessagesMessageSentIterator) Next() bool { +func (it *GroupMessagesInitializedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -226,7 +674,7 @@ func (it *GroupMessagesMessageSentIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(GroupMessagesMessageSent) + it.Event = new(GroupMessagesInitialized) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -241,7 +689,7 @@ func (it *GroupMessagesMessageSentIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(GroupMessagesMessageSent) + it.Event = new(GroupMessagesInitialized) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -257,43 +705,41 @@ func (it *GroupMessagesMessageSentIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *GroupMessagesMessageSentIterator) Error() error { +func (it *GroupMessagesInitializedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *GroupMessagesMessageSentIterator) Close() error { +func (it *GroupMessagesInitializedIterator) Close() error { it.sub.Unsubscribe() return nil } -// GroupMessagesMessageSent represents a MessageSent event raised by the GroupMessages contract. -type GroupMessagesMessageSent struct { - GroupId [32]byte - Message []byte - SequenceId uint64 - Raw types.Log // Blockchain specific contextual infos +// GroupMessagesInitialized represents a Initialized event raised by the GroupMessages contract. +type GroupMessagesInitialized struct { + Version uint64 + Raw types.Log // Blockchain specific contextual infos } -// FilterMessageSent is a free log retrieval operation binding the contract event 0x91f47151424884a46811ed593aa8a02ee5012e9332a4dcf1e9236a8ed4443c3e. +// FilterInitialized is a free log retrieval operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. // -// Solidity: event MessageSent(bytes32 groupId, bytes message, uint64 sequenceId) -func (_GroupMessages *GroupMessagesFilterer) FilterMessageSent(opts *bind.FilterOpts) (*GroupMessagesMessageSentIterator, error) { +// Solidity: event Initialized(uint64 version) +func (_GroupMessages *GroupMessagesFilterer) FilterInitialized(opts *bind.FilterOpts) (*GroupMessagesInitializedIterator, error) { - logs, sub, err := _GroupMessages.contract.FilterLogs(opts, "MessageSent") + logs, sub, err := _GroupMessages.contract.FilterLogs(opts, "Initialized") if err != nil { return nil, err } - return &GroupMessagesMessageSentIterator{contract: _GroupMessages.contract, event: "MessageSent", logs: logs, sub: sub}, nil + return &GroupMessagesInitializedIterator{contract: _GroupMessages.contract, event: "Initialized", logs: logs, sub: sub}, nil } -// WatchMessageSent is a free log subscription operation binding the contract event 0x91f47151424884a46811ed593aa8a02ee5012e9332a4dcf1e9236a8ed4443c3e. +// WatchInitialized is a free log subscription operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. // -// Solidity: event MessageSent(bytes32 groupId, bytes message, uint64 sequenceId) -func (_GroupMessages *GroupMessagesFilterer) WatchMessageSent(opts *bind.WatchOpts, sink chan<- *GroupMessagesMessageSent) (event.Subscription, error) { +// Solidity: event Initialized(uint64 version) +func (_GroupMessages *GroupMessagesFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *GroupMessagesInitialized) (event.Subscription, error) { - logs, sub, err := _GroupMessages.contract.WatchLogs(opts, "MessageSent") + logs, sub, err := _GroupMessages.contract.WatchLogs(opts, "Initialized") if err != nil { return nil, err } @@ -303,8 +749,8 @@ func (_GroupMessages *GroupMessagesFilterer) WatchMessageSent(opts *bind.WatchOp select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(GroupMessagesMessageSent) - if err := _GroupMessages.contract.UnpackLog(event, "MessageSent", log); err != nil { + event := new(GroupMessagesInitialized) + if err := _GroupMessages.contract.UnpackLog(event, "Initialized", log); err != nil { return err } event.Raw = log @@ -325,12 +771,1181 @@ func (_GroupMessages *GroupMessagesFilterer) WatchMessageSent(opts *bind.WatchOp }), nil } -// ParseMessageSent is a log parse operation binding the contract event 0x91f47151424884a46811ed593aa8a02ee5012e9332a4dcf1e9236a8ed4443c3e. +// ParseInitialized is a log parse operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. // -// Solidity: event MessageSent(bytes32 groupId, bytes message, uint64 sequenceId) -func (_GroupMessages *GroupMessagesFilterer) ParseMessageSent(log types.Log) (*GroupMessagesMessageSent, error) { - event := new(GroupMessagesMessageSent) - if err := _GroupMessages.contract.UnpackLog(event, "MessageSent", log); err != nil { +// Solidity: event Initialized(uint64 version) +func (_GroupMessages *GroupMessagesFilterer) ParseInitialized(log types.Log) (*GroupMessagesInitialized, error) { + event := new(GroupMessagesInitialized) + if err := _GroupMessages.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// GroupMessagesMessageSentIterator is returned from FilterMessageSent and is used to iterate over the raw logs and unpacked data for MessageSent events raised by the GroupMessages contract. +type GroupMessagesMessageSentIterator struct { + Event *GroupMessagesMessageSent // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *GroupMessagesMessageSentIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(GroupMessagesMessageSent) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(GroupMessagesMessageSent) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *GroupMessagesMessageSentIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *GroupMessagesMessageSentIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// GroupMessagesMessageSent represents a MessageSent event raised by the GroupMessages contract. +type GroupMessagesMessageSent struct { + GroupId [32]byte + Message []byte + SequenceId uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterMessageSent is a free log retrieval operation binding the contract event 0x91f47151424884a46811ed593aa8a02ee5012e9332a4dcf1e9236a8ed4443c3e. +// +// Solidity: event MessageSent(bytes32 groupId, bytes message, uint64 sequenceId) +func (_GroupMessages *GroupMessagesFilterer) FilterMessageSent(opts *bind.FilterOpts) (*GroupMessagesMessageSentIterator, error) { + + logs, sub, err := _GroupMessages.contract.FilterLogs(opts, "MessageSent") + if err != nil { + return nil, err + } + return &GroupMessagesMessageSentIterator{contract: _GroupMessages.contract, event: "MessageSent", logs: logs, sub: sub}, nil +} + +// WatchMessageSent is a free log subscription operation binding the contract event 0x91f47151424884a46811ed593aa8a02ee5012e9332a4dcf1e9236a8ed4443c3e. +// +// Solidity: event MessageSent(bytes32 groupId, bytes message, uint64 sequenceId) +func (_GroupMessages *GroupMessagesFilterer) WatchMessageSent(opts *bind.WatchOpts, sink chan<- *GroupMessagesMessageSent) (event.Subscription, error) { + + logs, sub, err := _GroupMessages.contract.WatchLogs(opts, "MessageSent") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(GroupMessagesMessageSent) + if err := _GroupMessages.contract.UnpackLog(event, "MessageSent", 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 +} + +// ParseMessageSent is a log parse operation binding the contract event 0x91f47151424884a46811ed593aa8a02ee5012e9332a4dcf1e9236a8ed4443c3e. +// +// Solidity: event MessageSent(bytes32 groupId, bytes message, uint64 sequenceId) +func (_GroupMessages *GroupMessagesFilterer) ParseMessageSent(log types.Log) (*GroupMessagesMessageSent, error) { + event := new(GroupMessagesMessageSent) + if err := _GroupMessages.contract.UnpackLog(event, "MessageSent", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// GroupMessagesPausedIterator is returned from FilterPaused and is used to iterate over the raw logs and unpacked data for Paused events raised by the GroupMessages contract. +type GroupMessagesPausedIterator struct { + Event *GroupMessagesPaused // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *GroupMessagesPausedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(GroupMessagesPaused) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(GroupMessagesPaused) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *GroupMessagesPausedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *GroupMessagesPausedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// GroupMessagesPaused represents a Paused event raised by the GroupMessages contract. +type GroupMessagesPaused struct { + Account common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterPaused is a free log retrieval operation binding the contract event 0x62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258. +// +// Solidity: event Paused(address account) +func (_GroupMessages *GroupMessagesFilterer) FilterPaused(opts *bind.FilterOpts) (*GroupMessagesPausedIterator, error) { + + logs, sub, err := _GroupMessages.contract.FilterLogs(opts, "Paused") + if err != nil { + return nil, err + } + return &GroupMessagesPausedIterator{contract: _GroupMessages.contract, event: "Paused", logs: logs, sub: sub}, nil +} + +// WatchPaused is a free log subscription operation binding the contract event 0x62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258. +// +// Solidity: event Paused(address account) +func (_GroupMessages *GroupMessagesFilterer) WatchPaused(opts *bind.WatchOpts, sink chan<- *GroupMessagesPaused) (event.Subscription, error) { + + logs, sub, err := _GroupMessages.contract.WatchLogs(opts, "Paused") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(GroupMessagesPaused) + if err := _GroupMessages.contract.UnpackLog(event, "Paused", 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 +} + +// ParsePaused is a log parse operation binding the contract event 0x62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258. +// +// Solidity: event Paused(address account) +func (_GroupMessages *GroupMessagesFilterer) ParsePaused(log types.Log) (*GroupMessagesPaused, error) { + event := new(GroupMessagesPaused) + if err := _GroupMessages.contract.UnpackLog(event, "Paused", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// GroupMessagesRoleAdminChangedIterator is returned from FilterRoleAdminChanged and is used to iterate over the raw logs and unpacked data for RoleAdminChanged events raised by the GroupMessages contract. +type GroupMessagesRoleAdminChangedIterator struct { + Event *GroupMessagesRoleAdminChanged // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *GroupMessagesRoleAdminChangedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(GroupMessagesRoleAdminChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(GroupMessagesRoleAdminChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *GroupMessagesRoleAdminChangedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *GroupMessagesRoleAdminChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// GroupMessagesRoleAdminChanged represents a RoleAdminChanged event raised by the GroupMessages contract. +type GroupMessagesRoleAdminChanged struct { + Role [32]byte + PreviousAdminRole [32]byte + NewAdminRole [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRoleAdminChanged is a free log retrieval operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_GroupMessages *GroupMessagesFilterer) FilterRoleAdminChanged(opts *bind.FilterOpts, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (*GroupMessagesRoleAdminChangedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) + } + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) + } + + logs, sub, err := _GroupMessages.contract.FilterLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) + if err != nil { + return nil, err + } + return &GroupMessagesRoleAdminChangedIterator{contract: _GroupMessages.contract, event: "RoleAdminChanged", logs: logs, sub: sub}, nil +} + +// WatchRoleAdminChanged is a free log subscription operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_GroupMessages *GroupMessagesFilterer) WatchRoleAdminChanged(opts *bind.WatchOpts, sink chan<- *GroupMessagesRoleAdminChanged, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) + } + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) + } + + logs, sub, err := _GroupMessages.contract.WatchLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(GroupMessagesRoleAdminChanged) + if err := _GroupMessages.contract.UnpackLog(event, "RoleAdminChanged", 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 +} + +// ParseRoleAdminChanged is a log parse operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_GroupMessages *GroupMessagesFilterer) ParseRoleAdminChanged(log types.Log) (*GroupMessagesRoleAdminChanged, error) { + event := new(GroupMessagesRoleAdminChanged) + if err := _GroupMessages.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// GroupMessagesRoleGrantedIterator is returned from FilterRoleGranted and is used to iterate over the raw logs and unpacked data for RoleGranted events raised by the GroupMessages contract. +type GroupMessagesRoleGrantedIterator struct { + Event *GroupMessagesRoleGranted // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *GroupMessagesRoleGrantedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(GroupMessagesRoleGranted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(GroupMessagesRoleGranted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *GroupMessagesRoleGrantedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *GroupMessagesRoleGrantedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// GroupMessagesRoleGranted represents a RoleGranted event raised by the GroupMessages contract. +type GroupMessagesRoleGranted struct { + Role [32]byte + Account common.Address + Sender common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRoleGranted is a free log retrieval operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_GroupMessages *GroupMessagesFilterer) FilterRoleGranted(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*GroupMessagesRoleGrantedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _GroupMessages.contract.FilterLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return &GroupMessagesRoleGrantedIterator{contract: _GroupMessages.contract, event: "RoleGranted", logs: logs, sub: sub}, nil +} + +// WatchRoleGranted is a free log subscription operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_GroupMessages *GroupMessagesFilterer) WatchRoleGranted(opts *bind.WatchOpts, sink chan<- *GroupMessagesRoleGranted, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _GroupMessages.contract.WatchLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(GroupMessagesRoleGranted) + if err := _GroupMessages.contract.UnpackLog(event, "RoleGranted", 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 +} + +// ParseRoleGranted is a log parse operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_GroupMessages *GroupMessagesFilterer) ParseRoleGranted(log types.Log) (*GroupMessagesRoleGranted, error) { + event := new(GroupMessagesRoleGranted) + if err := _GroupMessages.contract.UnpackLog(event, "RoleGranted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// GroupMessagesRoleRevokedIterator is returned from FilterRoleRevoked and is used to iterate over the raw logs and unpacked data for RoleRevoked events raised by the GroupMessages contract. +type GroupMessagesRoleRevokedIterator struct { + Event *GroupMessagesRoleRevoked // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *GroupMessagesRoleRevokedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(GroupMessagesRoleRevoked) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(GroupMessagesRoleRevoked) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *GroupMessagesRoleRevokedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *GroupMessagesRoleRevokedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// GroupMessagesRoleRevoked represents a RoleRevoked event raised by the GroupMessages contract. +type GroupMessagesRoleRevoked struct { + Role [32]byte + Account common.Address + Sender common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRoleRevoked is a free log retrieval operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_GroupMessages *GroupMessagesFilterer) FilterRoleRevoked(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*GroupMessagesRoleRevokedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _GroupMessages.contract.FilterLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return &GroupMessagesRoleRevokedIterator{contract: _GroupMessages.contract, event: "RoleRevoked", logs: logs, sub: sub}, nil +} + +// WatchRoleRevoked is a free log subscription operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_GroupMessages *GroupMessagesFilterer) WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- *GroupMessagesRoleRevoked, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _GroupMessages.contract.WatchLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(GroupMessagesRoleRevoked) + if err := _GroupMessages.contract.UnpackLog(event, "RoleRevoked", 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 +} + +// ParseRoleRevoked is a log parse operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_GroupMessages *GroupMessagesFilterer) ParseRoleRevoked(log types.Log) (*GroupMessagesRoleRevoked, error) { + event := new(GroupMessagesRoleRevoked) + if err := _GroupMessages.contract.UnpackLog(event, "RoleRevoked", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// GroupMessagesUnpausedIterator is returned from FilterUnpaused and is used to iterate over the raw logs and unpacked data for Unpaused events raised by the GroupMessages contract. +type GroupMessagesUnpausedIterator struct { + Event *GroupMessagesUnpaused // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *GroupMessagesUnpausedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(GroupMessagesUnpaused) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(GroupMessagesUnpaused) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *GroupMessagesUnpausedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *GroupMessagesUnpausedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// GroupMessagesUnpaused represents a Unpaused event raised by the GroupMessages contract. +type GroupMessagesUnpaused struct { + Account common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUnpaused is a free log retrieval operation binding the contract event 0x5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa. +// +// Solidity: event Unpaused(address account) +func (_GroupMessages *GroupMessagesFilterer) FilterUnpaused(opts *bind.FilterOpts) (*GroupMessagesUnpausedIterator, error) { + + logs, sub, err := _GroupMessages.contract.FilterLogs(opts, "Unpaused") + if err != nil { + return nil, err + } + return &GroupMessagesUnpausedIterator{contract: _GroupMessages.contract, event: "Unpaused", logs: logs, sub: sub}, nil +} + +// WatchUnpaused is a free log subscription operation binding the contract event 0x5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa. +// +// Solidity: event Unpaused(address account) +func (_GroupMessages *GroupMessagesFilterer) WatchUnpaused(opts *bind.WatchOpts, sink chan<- *GroupMessagesUnpaused) (event.Subscription, error) { + + logs, sub, err := _GroupMessages.contract.WatchLogs(opts, "Unpaused") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(GroupMessagesUnpaused) + if err := _GroupMessages.contract.UnpackLog(event, "Unpaused", 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 +} + +// ParseUnpaused is a log parse operation binding the contract event 0x5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa. +// +// Solidity: event Unpaused(address account) +func (_GroupMessages *GroupMessagesFilterer) ParseUnpaused(log types.Log) (*GroupMessagesUnpaused, error) { + event := new(GroupMessagesUnpaused) + if err := _GroupMessages.contract.UnpackLog(event, "Unpaused", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// GroupMessagesUpgradeAuthorizedIterator is returned from FilterUpgradeAuthorized and is used to iterate over the raw logs and unpacked data for UpgradeAuthorized events raised by the GroupMessages contract. +type GroupMessagesUpgradeAuthorizedIterator struct { + Event *GroupMessagesUpgradeAuthorized // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *GroupMessagesUpgradeAuthorizedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(GroupMessagesUpgradeAuthorized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(GroupMessagesUpgradeAuthorized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *GroupMessagesUpgradeAuthorizedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *GroupMessagesUpgradeAuthorizedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// GroupMessagesUpgradeAuthorized represents a UpgradeAuthorized event raised by the GroupMessages contract. +type GroupMessagesUpgradeAuthorized struct { + Upgrader common.Address + NewImplementation common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUpgradeAuthorized is a free log retrieval operation binding the contract event 0xd30e1d298bf814ea43d22b4ce8298062b08609cd67496483769d836157dd52fa. +// +// Solidity: event UpgradeAuthorized(address upgrader, address newImplementation) +func (_GroupMessages *GroupMessagesFilterer) FilterUpgradeAuthorized(opts *bind.FilterOpts) (*GroupMessagesUpgradeAuthorizedIterator, error) { + + logs, sub, err := _GroupMessages.contract.FilterLogs(opts, "UpgradeAuthorized") + if err != nil { + return nil, err + } + return &GroupMessagesUpgradeAuthorizedIterator{contract: _GroupMessages.contract, event: "UpgradeAuthorized", logs: logs, sub: sub}, nil +} + +// WatchUpgradeAuthorized is a free log subscription operation binding the contract event 0xd30e1d298bf814ea43d22b4ce8298062b08609cd67496483769d836157dd52fa. +// +// Solidity: event UpgradeAuthorized(address upgrader, address newImplementation) +func (_GroupMessages *GroupMessagesFilterer) WatchUpgradeAuthorized(opts *bind.WatchOpts, sink chan<- *GroupMessagesUpgradeAuthorized) (event.Subscription, error) { + + logs, sub, err := _GroupMessages.contract.WatchLogs(opts, "UpgradeAuthorized") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(GroupMessagesUpgradeAuthorized) + if err := _GroupMessages.contract.UnpackLog(event, "UpgradeAuthorized", 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 +} + +// ParseUpgradeAuthorized is a log parse operation binding the contract event 0xd30e1d298bf814ea43d22b4ce8298062b08609cd67496483769d836157dd52fa. +// +// Solidity: event UpgradeAuthorized(address upgrader, address newImplementation) +func (_GroupMessages *GroupMessagesFilterer) ParseUpgradeAuthorized(log types.Log) (*GroupMessagesUpgradeAuthorized, error) { + event := new(GroupMessagesUpgradeAuthorized) + if err := _GroupMessages.contract.UnpackLog(event, "UpgradeAuthorized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// GroupMessagesUpgradedIterator is returned from FilterUpgraded and is used to iterate over the raw logs and unpacked data for Upgraded events raised by the GroupMessages contract. +type GroupMessagesUpgradedIterator struct { + Event *GroupMessagesUpgraded // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *GroupMessagesUpgradedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(GroupMessagesUpgraded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(GroupMessagesUpgraded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *GroupMessagesUpgradedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *GroupMessagesUpgradedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// GroupMessagesUpgraded represents a Upgraded event raised by the GroupMessages contract. +type GroupMessagesUpgraded struct { + Implementation common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUpgraded is a free log retrieval operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_GroupMessages *GroupMessagesFilterer) FilterUpgraded(opts *bind.FilterOpts, implementation []common.Address) (*GroupMessagesUpgradedIterator, error) { + + var implementationRule []interface{} + for _, implementationItem := range implementation { + implementationRule = append(implementationRule, implementationItem) + } + + logs, sub, err := _GroupMessages.contract.FilterLogs(opts, "Upgraded", implementationRule) + if err != nil { + return nil, err + } + return &GroupMessagesUpgradedIterator{contract: _GroupMessages.contract, event: "Upgraded", logs: logs, sub: sub}, nil +} + +// WatchUpgraded is a free log subscription operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_GroupMessages *GroupMessagesFilterer) WatchUpgraded(opts *bind.WatchOpts, sink chan<- *GroupMessagesUpgraded, implementation []common.Address) (event.Subscription, error) { + + var implementationRule []interface{} + for _, implementationItem := range implementation { + implementationRule = append(implementationRule, implementationItem) + } + + logs, sub, err := _GroupMessages.contract.WatchLogs(opts, "Upgraded", implementationRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(GroupMessagesUpgraded) + if err := _GroupMessages.contract.UnpackLog(event, "Upgraded", 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 +} + +// ParseUpgraded is a log parse operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_GroupMessages *GroupMessagesFilterer) ParseUpgraded(log types.Log) (*GroupMessagesUpgraded, error) { + event := new(GroupMessagesUpgraded) + if err := _GroupMessages.contract.UnpackLog(event, "Upgraded", log); err != nil { return nil, err } event.Raw = log diff --git a/pkg/abis/identityUpdates.go b/pkg/abis/identityUpdates.go index fd84d11d..1a1b5af4 100644 --- a/pkg/abis/identityUpdates.go +++ b/pkg/abis/identityUpdates.go @@ -31,13 +31,35 @@ var ( // IdentityUpdatesMetaData contains all meta data concerning the IdentityUpdates contract. var IdentityUpdatesMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"function\",\"name\":\"addIdentityUpdate\",\"inputs\":[{\"name\":\"inboxId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"update\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"IdentityUpdateCreated\",\"inputs\":[{\"name\":\"inboxId\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"update\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"sequenceId\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false}]", + ABI: "[{\"type\":\"function\",\"name\":\"DEFAULT_ADMIN_ROLE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MAX_PAYLOAD_SIZE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MIN_PAYLOAD_SIZE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"UPGRADE_INTERFACE_VERSION\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"addIdentityUpdate\",\"inputs\":[{\"name\":\"inboxId\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"update\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getRoleAdmin\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"grantRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"hasRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"_admin\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"pause\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"paused\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proxiableUUID\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"renounceRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"callerConfirmation\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"revokeRole\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"unpause\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"inputs\":[{\"name\":\"newImplementation\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"event\",\"name\":\"IdentityUpdateCreated\",\"inputs\":[{\"name\":\"inboxId\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"update\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"sequenceId\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Paused\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleAdminChanged\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"previousAdminRole\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"newAdminRole\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleGranted\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RoleRevoked\",\"inputs\":[{\"name\":\"role\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"account\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"sender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Unpaused\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"UpgradeAuthorized\",\"inputs\":[{\"name\":\"upgrader\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"newImplementation\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Upgraded\",\"inputs\":[{\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AccessControlBadConfirmation\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AccessControlUnauthorizedAccount\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"neededRole\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"AddressEmptyCode\",\"inputs\":[{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ERC1967InvalidImplementation\",\"inputs\":[{\"name\":\"implementation\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ERC1967NonPayable\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"EnforcedPause\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ExpectedPause\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"FailedCall\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidPayloadSize\",\"inputs\":[{\"name\":\"actualSize\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"minSize\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"maxSize\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UUPSUnauthorizedCallContext\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UUPSUnsupportedProxiableUUID\",\"inputs\":[{\"name\":\"slot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"ZeroAdminAddress\",\"inputs\":[]}]", + Bin: "0x60a0604052306080523480156012575f5ffd5b506080516117be6100395f395f8181610b4601528181610b6f0152610e8401526117be5ff3fe608060405260043610610109575f3560e01c80638456cb59116100a1578063ad3cb1cc11610071578063c4d66de811610057578063c4d66de81461036e578063d547741f1461038d578063f5368506146103ac575f5ffd5b8063ad3cb1cc146102fa578063ba74fc7c1461034f575f5ffd5b80638456cb591461024d57806391d1485414610261578063a217fddf146102d1578063a2ba1934146102e4575f5ffd5b80633f4ba83a116100dc5780633f4ba83a146101dc5780634f1ef286146101f057806352d1902d146102035780635c975abb14610217575f5ffd5b806301ffc9a71461010d578063248a9ca3146101415780632f2ff15d1461019c57806336568abe146101bd575b5f5ffd5b348015610118575f5ffd5b5061012c61012736600461143c565b6103c0565b60405190151581526020015b60405180910390f35b34801561014c575f5ffd5b5061018e61015b36600461147b565b5f9081527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052604090206001015490565b604051908152602001610138565b3480156101a7575f5ffd5b506101bb6101b63660046114ba565b610458565b005b3480156101c8575f5ffd5b506101bb6101d73660046114ba565b6104a1565b3480156101e7575f5ffd5b506101bb6104ff565b6101bb6101fe366004611511565b610514565b34801561020e575f5ffd5b5061018e610533565b348015610222575f5ffd5b507fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff1661012c565b348015610258575f5ffd5b506101bb610561565b34801561026c575f5ffd5b5061012c61027b3660046114ba565b5f9182527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020908152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b3480156102dc575f5ffd5b5061018e5f81565b3480156102ef575f5ffd5b5061018e6240000081565b348015610305575f5ffd5b506103426040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101389190611612565b34801561035a575f5ffd5b506101bb610369366004611665565b610573565b348015610379575f5ffd5b506101bb6103883660046116dc565b610665565b348015610398575f5ffd5b506101bb6103a73660046114ba565b61084a565b3480156103b7575f5ffd5b5061018e606881565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061045257507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260409020600101546104918161088d565b61049b8383610897565b50505050565b73ffffffffffffffffffffffffffffffffffffffff811633146104f0576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104fa82826109b5565b505050565b5f6105098161088d565b610511610a91565b50565b61051c610b2e565b61052582610c34565b61052f8282610d33565b5050565b5f61053c610e6c565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b5f61056b8161088d565b610511610edb565b61057b610f54565b6068811080159061058f5750624000008111155b819060689062400000906105e5576040517f93b7abe60000000000000000000000000000000000000000000000000000000081526004810193909352602483019190915260448201526064015b60405180910390fd5b50505f805467ffffffffffffffff808216600101167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090911681179091556040517fc1a40f292090ec0435e939cdfe248e0322a88566679a90a50c4e9e5ef762dbd59250610658918691869186916116f5565b60405180910390a1505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f811580156106af5750825b90505f8267ffffffffffffffff1660011480156106cb5750303b155b9050811580156106d9575080155b15610710576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117855583156107715784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b73ffffffffffffffffffffffffffffffffffffffff86166107be576040517f3ef39b8100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107c6610fb0565b6107ce610fb0565b6107d6610fb8565b6107e05f87610897565b5083156108425784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260409020600101546108838161088d565b61049b83836109b5565b6105118133610fc8565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020818152604080842073ffffffffffffffffffffffffffffffffffffffff8616855290915282205460ff166109ac575f8481526020828152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556109483390565b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a46001915050610452565b5f915050610452565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020818152604080842073ffffffffffffffffffffffffffffffffffffffff8616855290915282205460ff16156109ac575f8481526020828152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a46001915050610452565b610a9961106e565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001681557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a150565b3073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480610bfb57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16610be27f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614155b15610c32576040517fe07c8dba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b5f610c3e8161088d565b73ffffffffffffffffffffffffffffffffffffffff8216610ce1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4e657720696d706c656d656e746174696f6e2063616e6e6f74206265207a657260448201527f6f2061646472657373000000000000000000000000000000000000000000000060648201526084016105dc565b6040805133815273ffffffffffffffffffffffffffffffffffffffff841660208201527fd30e1d298bf814ea43d22b4ce8298062b08609cd67496483769d836157dd52fa910160405180910390a15050565b8173ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610db8575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252610db59181019061175b565b60015b610e06576040517f4c9c8ce300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024016105dc565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114610e62576040517faa1d49a4000000000000000000000000000000000000000000000000000000008152600481018290526024016105dc565b6104fa83836110c9565b3073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610c32576040517fe07c8dba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ee3610f54565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011781557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25833610b03565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff1615610c32576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c3261112b565b610fc061112b565b610c32611192565b5f8281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff1661052f576040517fe2517d3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602481018390526044016105dc565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033005460ff16610c32576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110d2826111e3565b60405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115611123576104fa82826112b1565b61052f611330565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff16610c32576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61119a61112b565b7fcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b8073ffffffffffffffffffffffffffffffffffffffff163b5f0361124b576040517f4c9c8ce300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016105dc565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60605f5f8473ffffffffffffffffffffffffffffffffffffffff16846040516112da9190611772565b5f60405180830381855af49150503d805f8114611312576040519150601f19603f3d011682016040523d82523d5f602084013e611317565b606091505b5091509150611327858383611368565b95945050505050565b3415610c32576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608261137d57611378826113fa565b6113f3565b81511580156113a1575073ffffffffffffffffffffffffffffffffffffffff84163b155b156113f0576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016105dc565b50805b9392505050565b80511561140a5780518082602001fd5b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6020828403121561144c575f5ffd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146113f3575f5ffd5b5f6020828403121561148b575f5ffd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff811681146114b5575f5ffd5b919050565b5f5f604083850312156114cb575f5ffd5b823591506114db60208401611492565b90509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f5f60408385031215611522575f5ffd5b61152b83611492565b9150602083013567ffffffffffffffff811115611546575f5ffd5b8301601f81018513611556575f5ffd5b803567ffffffffffffffff811115611570576115706114e4565b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8501160116810181811067ffffffffffffffff821117156115dc576115dc6114e4565b6040528181528282016020018710156115f3575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b5f5f5f60408486031215611677575f5ffd5b83359250602084013567ffffffffffffffff811115611694575f5ffd5b8401601f810186136116a4575f5ffd5b803567ffffffffffffffff8111156116ba575f5ffd5b8660208284010111156116cb575f5ffd5b939660209190910195509293505050565b5f602082840312156116ec575f5ffd5b6113f382611492565b84815260606020820152826060820152828460808301375f608084830101525f60807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116830101905067ffffffffffffffff8316604083015295945050505050565b5f6020828403121561176b575f5ffd5b5051919050565b5f82518060208501845e5f92019182525091905056fea26469706673582212202d65f062d705cb761a34070256e7c4f8eab20ae6669f6158830cb02fcd42c16164736f6c634300081c0033", } // IdentityUpdatesABI is the input ABI used to generate the binding from. // Deprecated: Use IdentityUpdatesMetaData.ABI instead. var IdentityUpdatesABI = IdentityUpdatesMetaData.ABI +// IdentityUpdatesBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use IdentityUpdatesMetaData.Bin instead. +var IdentityUpdatesBin = IdentityUpdatesMetaData.Bin + +// DeployIdentityUpdates deploys a new Ethereum contract, binding an instance of IdentityUpdates to it. +func DeployIdentityUpdates(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *IdentityUpdates, error) { + parsed, err := IdentityUpdatesMetaData.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(IdentityUpdatesBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &IdentityUpdates{IdentityUpdatesCaller: IdentityUpdatesCaller{contract: contract}, IdentityUpdatesTransactor: IdentityUpdatesTransactor{contract: contract}, IdentityUpdatesFilterer: IdentityUpdatesFilterer{contract: contract}}, nil +} + // IdentityUpdates is an auto generated Go binding around an Ethereum contract. type IdentityUpdates struct { IdentityUpdatesCaller // Read-only binding to the contract @@ -180,6 +202,285 @@ func (_IdentityUpdates *IdentityUpdatesTransactorRaw) Transact(opts *bind.Transa return _IdentityUpdates.Contract.contract.Transact(opts, method, params...) } +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_IdentityUpdates *IdentityUpdatesCaller) DEFAULTADMINROLE(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _IdentityUpdates.contract.Call(opts, &out, "DEFAULT_ADMIN_ROLE") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_IdentityUpdates *IdentityUpdatesSession) DEFAULTADMINROLE() ([32]byte, error) { + return _IdentityUpdates.Contract.DEFAULTADMINROLE(&_IdentityUpdates.CallOpts) +} + +// DEFAULTADMINROLE is a free data retrieval call binding the contract method 0xa217fddf. +// +// Solidity: function DEFAULT_ADMIN_ROLE() view returns(bytes32) +func (_IdentityUpdates *IdentityUpdatesCallerSession) DEFAULTADMINROLE() ([32]byte, error) { + return _IdentityUpdates.Contract.DEFAULTADMINROLE(&_IdentityUpdates.CallOpts) +} + +// MAXPAYLOADSIZE is a free data retrieval call binding the contract method 0xa2ba1934. +// +// Solidity: function MAX_PAYLOAD_SIZE() view returns(uint256) +func (_IdentityUpdates *IdentityUpdatesCaller) MAXPAYLOADSIZE(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _IdentityUpdates.contract.Call(opts, &out, "MAX_PAYLOAD_SIZE") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// MAXPAYLOADSIZE is a free data retrieval call binding the contract method 0xa2ba1934. +// +// Solidity: function MAX_PAYLOAD_SIZE() view returns(uint256) +func (_IdentityUpdates *IdentityUpdatesSession) MAXPAYLOADSIZE() (*big.Int, error) { + return _IdentityUpdates.Contract.MAXPAYLOADSIZE(&_IdentityUpdates.CallOpts) +} + +// MAXPAYLOADSIZE is a free data retrieval call binding the contract method 0xa2ba1934. +// +// Solidity: function MAX_PAYLOAD_SIZE() view returns(uint256) +func (_IdentityUpdates *IdentityUpdatesCallerSession) MAXPAYLOADSIZE() (*big.Int, error) { + return _IdentityUpdates.Contract.MAXPAYLOADSIZE(&_IdentityUpdates.CallOpts) +} + +// MINPAYLOADSIZE is a free data retrieval call binding the contract method 0xf5368506. +// +// Solidity: function MIN_PAYLOAD_SIZE() view returns(uint256) +func (_IdentityUpdates *IdentityUpdatesCaller) MINPAYLOADSIZE(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _IdentityUpdates.contract.Call(opts, &out, "MIN_PAYLOAD_SIZE") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// MINPAYLOADSIZE is a free data retrieval call binding the contract method 0xf5368506. +// +// Solidity: function MIN_PAYLOAD_SIZE() view returns(uint256) +func (_IdentityUpdates *IdentityUpdatesSession) MINPAYLOADSIZE() (*big.Int, error) { + return _IdentityUpdates.Contract.MINPAYLOADSIZE(&_IdentityUpdates.CallOpts) +} + +// MINPAYLOADSIZE is a free data retrieval call binding the contract method 0xf5368506. +// +// Solidity: function MIN_PAYLOAD_SIZE() view returns(uint256) +func (_IdentityUpdates *IdentityUpdatesCallerSession) MINPAYLOADSIZE() (*big.Int, error) { + return _IdentityUpdates.Contract.MINPAYLOADSIZE(&_IdentityUpdates.CallOpts) +} + +// UPGRADEINTERFACEVERSION is a free data retrieval call binding the contract method 0xad3cb1cc. +// +// Solidity: function UPGRADE_INTERFACE_VERSION() view returns(string) +func (_IdentityUpdates *IdentityUpdatesCaller) UPGRADEINTERFACEVERSION(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _IdentityUpdates.contract.Call(opts, &out, "UPGRADE_INTERFACE_VERSION") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// UPGRADEINTERFACEVERSION is a free data retrieval call binding the contract method 0xad3cb1cc. +// +// Solidity: function UPGRADE_INTERFACE_VERSION() view returns(string) +func (_IdentityUpdates *IdentityUpdatesSession) UPGRADEINTERFACEVERSION() (string, error) { + return _IdentityUpdates.Contract.UPGRADEINTERFACEVERSION(&_IdentityUpdates.CallOpts) +} + +// UPGRADEINTERFACEVERSION is a free data retrieval call binding the contract method 0xad3cb1cc. +// +// Solidity: function UPGRADE_INTERFACE_VERSION() view returns(string) +func (_IdentityUpdates *IdentityUpdatesCallerSession) UPGRADEINTERFACEVERSION() (string, error) { + return _IdentityUpdates.Contract.UPGRADEINTERFACEVERSION(&_IdentityUpdates.CallOpts) +} + +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_IdentityUpdates *IdentityUpdatesCaller) GetRoleAdmin(opts *bind.CallOpts, role [32]byte) ([32]byte, error) { + var out []interface{} + err := _IdentityUpdates.contract.Call(opts, &out, "getRoleAdmin", role) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_IdentityUpdates *IdentityUpdatesSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _IdentityUpdates.Contract.GetRoleAdmin(&_IdentityUpdates.CallOpts, role) +} + +// GetRoleAdmin is a free data retrieval call binding the contract method 0x248a9ca3. +// +// Solidity: function getRoleAdmin(bytes32 role) view returns(bytes32) +func (_IdentityUpdates *IdentityUpdatesCallerSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { + return _IdentityUpdates.Contract.GetRoleAdmin(&_IdentityUpdates.CallOpts, role) +} + +// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_IdentityUpdates *IdentityUpdatesCaller) HasRole(opts *bind.CallOpts, role [32]byte, account common.Address) (bool, error) { + var out []interface{} + err := _IdentityUpdates.contract.Call(opts, &out, "hasRole", role, account) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_IdentityUpdates *IdentityUpdatesSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _IdentityUpdates.Contract.HasRole(&_IdentityUpdates.CallOpts, role, account) +} + +// HasRole is a free data retrieval call binding the contract method 0x91d14854. +// +// Solidity: function hasRole(bytes32 role, address account) view returns(bool) +func (_IdentityUpdates *IdentityUpdatesCallerSession) HasRole(role [32]byte, account common.Address) (bool, error) { + return _IdentityUpdates.Contract.HasRole(&_IdentityUpdates.CallOpts, role, account) +} + +// Paused is a free data retrieval call binding the contract method 0x5c975abb. +// +// Solidity: function paused() view returns(bool) +func (_IdentityUpdates *IdentityUpdatesCaller) Paused(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _IdentityUpdates.contract.Call(opts, &out, "paused") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// Paused is a free data retrieval call binding the contract method 0x5c975abb. +// +// Solidity: function paused() view returns(bool) +func (_IdentityUpdates *IdentityUpdatesSession) Paused() (bool, error) { + return _IdentityUpdates.Contract.Paused(&_IdentityUpdates.CallOpts) +} + +// Paused is a free data retrieval call binding the contract method 0x5c975abb. +// +// Solidity: function paused() view returns(bool) +func (_IdentityUpdates *IdentityUpdatesCallerSession) Paused() (bool, error) { + return _IdentityUpdates.Contract.Paused(&_IdentityUpdates.CallOpts) +} + +// ProxiableUUID is a free data retrieval call binding the contract method 0x52d1902d. +// +// Solidity: function proxiableUUID() view returns(bytes32) +func (_IdentityUpdates *IdentityUpdatesCaller) ProxiableUUID(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _IdentityUpdates.contract.Call(opts, &out, "proxiableUUID") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// ProxiableUUID is a free data retrieval call binding the contract method 0x52d1902d. +// +// Solidity: function proxiableUUID() view returns(bytes32) +func (_IdentityUpdates *IdentityUpdatesSession) ProxiableUUID() ([32]byte, error) { + return _IdentityUpdates.Contract.ProxiableUUID(&_IdentityUpdates.CallOpts) +} + +// ProxiableUUID is a free data retrieval call binding the contract method 0x52d1902d. +// +// Solidity: function proxiableUUID() view returns(bytes32) +func (_IdentityUpdates *IdentityUpdatesCallerSession) ProxiableUUID() ([32]byte, error) { + return _IdentityUpdates.Contract.ProxiableUUID(&_IdentityUpdates.CallOpts) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_IdentityUpdates *IdentityUpdatesCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _IdentityUpdates.contract.Call(opts, &out, "supportsInterface", interfaceId) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_IdentityUpdates *IdentityUpdatesSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _IdentityUpdates.Contract.SupportsInterface(&_IdentityUpdates.CallOpts, interfaceId) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_IdentityUpdates *IdentityUpdatesCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _IdentityUpdates.Contract.SupportsInterface(&_IdentityUpdates.CallOpts, interfaceId) +} + // AddIdentityUpdate is a paid mutator transaction binding the contract method 0xba74fc7c. // // Solidity: function addIdentityUpdate(bytes32 inboxId, bytes update) returns() @@ -201,6 +502,153 @@ func (_IdentityUpdates *IdentityUpdatesTransactorSession) AddIdentityUpdate(inbo return _IdentityUpdates.Contract.AddIdentityUpdate(&_IdentityUpdates.TransactOpts, inboxId, update) } +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_IdentityUpdates *IdentityUpdatesTransactor) GrantRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _IdentityUpdates.contract.Transact(opts, "grantRole", role, account) +} + +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_IdentityUpdates *IdentityUpdatesSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _IdentityUpdates.Contract.GrantRole(&_IdentityUpdates.TransactOpts, role, account) +} + +// GrantRole is a paid mutator transaction binding the contract method 0x2f2ff15d. +// +// Solidity: function grantRole(bytes32 role, address account) returns() +func (_IdentityUpdates *IdentityUpdatesTransactorSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _IdentityUpdates.Contract.GrantRole(&_IdentityUpdates.TransactOpts, role, account) +} + +// Initialize is a paid mutator transaction binding the contract method 0xc4d66de8. +// +// Solidity: function initialize(address _admin) returns() +func (_IdentityUpdates *IdentityUpdatesTransactor) Initialize(opts *bind.TransactOpts, _admin common.Address) (*types.Transaction, error) { + return _IdentityUpdates.contract.Transact(opts, "initialize", _admin) +} + +// Initialize is a paid mutator transaction binding the contract method 0xc4d66de8. +// +// Solidity: function initialize(address _admin) returns() +func (_IdentityUpdates *IdentityUpdatesSession) Initialize(_admin common.Address) (*types.Transaction, error) { + return _IdentityUpdates.Contract.Initialize(&_IdentityUpdates.TransactOpts, _admin) +} + +// Initialize is a paid mutator transaction binding the contract method 0xc4d66de8. +// +// Solidity: function initialize(address _admin) returns() +func (_IdentityUpdates *IdentityUpdatesTransactorSession) Initialize(_admin common.Address) (*types.Transaction, error) { + return _IdentityUpdates.Contract.Initialize(&_IdentityUpdates.TransactOpts, _admin) +} + +// Pause is a paid mutator transaction binding the contract method 0x8456cb59. +// +// Solidity: function pause() returns() +func (_IdentityUpdates *IdentityUpdatesTransactor) Pause(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IdentityUpdates.contract.Transact(opts, "pause") +} + +// Pause is a paid mutator transaction binding the contract method 0x8456cb59. +// +// Solidity: function pause() returns() +func (_IdentityUpdates *IdentityUpdatesSession) Pause() (*types.Transaction, error) { + return _IdentityUpdates.Contract.Pause(&_IdentityUpdates.TransactOpts) +} + +// Pause is a paid mutator transaction binding the contract method 0x8456cb59. +// +// Solidity: function pause() returns() +func (_IdentityUpdates *IdentityUpdatesTransactorSession) Pause() (*types.Transaction, error) { + return _IdentityUpdates.Contract.Pause(&_IdentityUpdates.TransactOpts) +} + +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_IdentityUpdates *IdentityUpdatesTransactor) RenounceRole(opts *bind.TransactOpts, role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _IdentityUpdates.contract.Transact(opts, "renounceRole", role, callerConfirmation) +} + +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_IdentityUpdates *IdentityUpdatesSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _IdentityUpdates.Contract.RenounceRole(&_IdentityUpdates.TransactOpts, role, callerConfirmation) +} + +// RenounceRole is a paid mutator transaction binding the contract method 0x36568abe. +// +// Solidity: function renounceRole(bytes32 role, address callerConfirmation) returns() +func (_IdentityUpdates *IdentityUpdatesTransactorSession) RenounceRole(role [32]byte, callerConfirmation common.Address) (*types.Transaction, error) { + return _IdentityUpdates.Contract.RenounceRole(&_IdentityUpdates.TransactOpts, role, callerConfirmation) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_IdentityUpdates *IdentityUpdatesTransactor) RevokeRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { + return _IdentityUpdates.contract.Transact(opts, "revokeRole", role, account) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_IdentityUpdates *IdentityUpdatesSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _IdentityUpdates.Contract.RevokeRole(&_IdentityUpdates.TransactOpts, role, account) +} + +// RevokeRole is a paid mutator transaction binding the contract method 0xd547741f. +// +// Solidity: function revokeRole(bytes32 role, address account) returns() +func (_IdentityUpdates *IdentityUpdatesTransactorSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { + return _IdentityUpdates.Contract.RevokeRole(&_IdentityUpdates.TransactOpts, role, account) +} + +// Unpause is a paid mutator transaction binding the contract method 0x3f4ba83a. +// +// Solidity: function unpause() returns() +func (_IdentityUpdates *IdentityUpdatesTransactor) Unpause(opts *bind.TransactOpts) (*types.Transaction, error) { + return _IdentityUpdates.contract.Transact(opts, "unpause") +} + +// Unpause is a paid mutator transaction binding the contract method 0x3f4ba83a. +// +// Solidity: function unpause() returns() +func (_IdentityUpdates *IdentityUpdatesSession) Unpause() (*types.Transaction, error) { + return _IdentityUpdates.Contract.Unpause(&_IdentityUpdates.TransactOpts) +} + +// Unpause is a paid mutator transaction binding the contract method 0x3f4ba83a. +// +// Solidity: function unpause() returns() +func (_IdentityUpdates *IdentityUpdatesTransactorSession) Unpause() (*types.Transaction, error) { + return _IdentityUpdates.Contract.Unpause(&_IdentityUpdates.TransactOpts) +} + +// UpgradeToAndCall is a paid mutator transaction binding the contract method 0x4f1ef286. +// +// Solidity: function upgradeToAndCall(address newImplementation, bytes data) payable returns() +func (_IdentityUpdates *IdentityUpdatesTransactor) UpgradeToAndCall(opts *bind.TransactOpts, newImplementation common.Address, data []byte) (*types.Transaction, error) { + return _IdentityUpdates.contract.Transact(opts, "upgradeToAndCall", newImplementation, data) +} + +// UpgradeToAndCall is a paid mutator transaction binding the contract method 0x4f1ef286. +// +// Solidity: function upgradeToAndCall(address newImplementation, bytes data) payable returns() +func (_IdentityUpdates *IdentityUpdatesSession) UpgradeToAndCall(newImplementation common.Address, data []byte) (*types.Transaction, error) { + return _IdentityUpdates.Contract.UpgradeToAndCall(&_IdentityUpdates.TransactOpts, newImplementation, data) +} + +// UpgradeToAndCall is a paid mutator transaction binding the contract method 0x4f1ef286. +// +// Solidity: function upgradeToAndCall(address newImplementation, bytes data) payable returns() +func (_IdentityUpdates *IdentityUpdatesTransactorSession) UpgradeToAndCall(newImplementation common.Address, data []byte) (*types.Transaction, error) { + return _IdentityUpdates.Contract.UpgradeToAndCall(&_IdentityUpdates.TransactOpts, newImplementation, data) +} + // IdentityUpdatesIdentityUpdateCreatedIterator is returned from FilterIdentityUpdateCreated and is used to iterate over the raw logs and unpacked data for IdentityUpdateCreated events raised by the IdentityUpdates contract. type IdentityUpdatesIdentityUpdateCreatedIterator struct { Event *IdentityUpdatesIdentityUpdateCreated // Event containing the contract specifics and raw log @@ -336,3 +784,1170 @@ func (_IdentityUpdates *IdentityUpdatesFilterer) ParseIdentityUpdateCreated(log event.Raw = log return event, nil } + +// IdentityUpdatesInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the IdentityUpdates contract. +type IdentityUpdatesInitializedIterator struct { + Event *IdentityUpdatesInitialized // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IdentityUpdatesInitializedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IdentityUpdatesInitialized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IdentityUpdatesInitialized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IdentityUpdatesInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IdentityUpdatesInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IdentityUpdatesInitialized represents a Initialized event raised by the IdentityUpdates contract. +type IdentityUpdatesInitialized struct { + Version uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialized is a free log retrieval operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_IdentityUpdates *IdentityUpdatesFilterer) FilterInitialized(opts *bind.FilterOpts) (*IdentityUpdatesInitializedIterator, error) { + + logs, sub, err := _IdentityUpdates.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return &IdentityUpdatesInitializedIterator{contract: _IdentityUpdates.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_IdentityUpdates *IdentityUpdatesFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *IdentityUpdatesInitialized) (event.Subscription, error) { + + logs, sub, err := _IdentityUpdates.contract.WatchLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IdentityUpdatesInitialized) + if err := _IdentityUpdates.contract.UnpackLog(event, "Initialized", 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 +} + +// ParseInitialized is a log parse operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_IdentityUpdates *IdentityUpdatesFilterer) ParseInitialized(log types.Log) (*IdentityUpdatesInitialized, error) { + event := new(IdentityUpdatesInitialized) + if err := _IdentityUpdates.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IdentityUpdatesPausedIterator is returned from FilterPaused and is used to iterate over the raw logs and unpacked data for Paused events raised by the IdentityUpdates contract. +type IdentityUpdatesPausedIterator struct { + Event *IdentityUpdatesPaused // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IdentityUpdatesPausedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IdentityUpdatesPaused) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IdentityUpdatesPaused) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IdentityUpdatesPausedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IdentityUpdatesPausedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IdentityUpdatesPaused represents a Paused event raised by the IdentityUpdates contract. +type IdentityUpdatesPaused struct { + Account common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterPaused is a free log retrieval operation binding the contract event 0x62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258. +// +// Solidity: event Paused(address account) +func (_IdentityUpdates *IdentityUpdatesFilterer) FilterPaused(opts *bind.FilterOpts) (*IdentityUpdatesPausedIterator, error) { + + logs, sub, err := _IdentityUpdates.contract.FilterLogs(opts, "Paused") + if err != nil { + return nil, err + } + return &IdentityUpdatesPausedIterator{contract: _IdentityUpdates.contract, event: "Paused", logs: logs, sub: sub}, nil +} + +// WatchPaused is a free log subscription operation binding the contract event 0x62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258. +// +// Solidity: event Paused(address account) +func (_IdentityUpdates *IdentityUpdatesFilterer) WatchPaused(opts *bind.WatchOpts, sink chan<- *IdentityUpdatesPaused) (event.Subscription, error) { + + logs, sub, err := _IdentityUpdates.contract.WatchLogs(opts, "Paused") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IdentityUpdatesPaused) + if err := _IdentityUpdates.contract.UnpackLog(event, "Paused", 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 +} + +// ParsePaused is a log parse operation binding the contract event 0x62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258. +// +// Solidity: event Paused(address account) +func (_IdentityUpdates *IdentityUpdatesFilterer) ParsePaused(log types.Log) (*IdentityUpdatesPaused, error) { + event := new(IdentityUpdatesPaused) + if err := _IdentityUpdates.contract.UnpackLog(event, "Paused", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IdentityUpdatesRoleAdminChangedIterator is returned from FilterRoleAdminChanged and is used to iterate over the raw logs and unpacked data for RoleAdminChanged events raised by the IdentityUpdates contract. +type IdentityUpdatesRoleAdminChangedIterator struct { + Event *IdentityUpdatesRoleAdminChanged // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IdentityUpdatesRoleAdminChangedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IdentityUpdatesRoleAdminChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IdentityUpdatesRoleAdminChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IdentityUpdatesRoleAdminChangedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IdentityUpdatesRoleAdminChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IdentityUpdatesRoleAdminChanged represents a RoleAdminChanged event raised by the IdentityUpdates contract. +type IdentityUpdatesRoleAdminChanged struct { + Role [32]byte + PreviousAdminRole [32]byte + NewAdminRole [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRoleAdminChanged is a free log retrieval operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_IdentityUpdates *IdentityUpdatesFilterer) FilterRoleAdminChanged(opts *bind.FilterOpts, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (*IdentityUpdatesRoleAdminChangedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) + } + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) + } + + logs, sub, err := _IdentityUpdates.contract.FilterLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) + if err != nil { + return nil, err + } + return &IdentityUpdatesRoleAdminChangedIterator{contract: _IdentityUpdates.contract, event: "RoleAdminChanged", logs: logs, sub: sub}, nil +} + +// WatchRoleAdminChanged is a free log subscription operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_IdentityUpdates *IdentityUpdatesFilterer) WatchRoleAdminChanged(opts *bind.WatchOpts, sink chan<- *IdentityUpdatesRoleAdminChanged, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var previousAdminRoleRule []interface{} + for _, previousAdminRoleItem := range previousAdminRole { + previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) + } + var newAdminRoleRule []interface{} + for _, newAdminRoleItem := range newAdminRole { + newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) + } + + logs, sub, err := _IdentityUpdates.contract.WatchLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IdentityUpdatesRoleAdminChanged) + if err := _IdentityUpdates.contract.UnpackLog(event, "RoleAdminChanged", 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 +} + +// ParseRoleAdminChanged is a log parse operation binding the contract event 0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff. +// +// Solidity: event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole) +func (_IdentityUpdates *IdentityUpdatesFilterer) ParseRoleAdminChanged(log types.Log) (*IdentityUpdatesRoleAdminChanged, error) { + event := new(IdentityUpdatesRoleAdminChanged) + if err := _IdentityUpdates.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IdentityUpdatesRoleGrantedIterator is returned from FilterRoleGranted and is used to iterate over the raw logs and unpacked data for RoleGranted events raised by the IdentityUpdates contract. +type IdentityUpdatesRoleGrantedIterator struct { + Event *IdentityUpdatesRoleGranted // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IdentityUpdatesRoleGrantedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IdentityUpdatesRoleGranted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IdentityUpdatesRoleGranted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IdentityUpdatesRoleGrantedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IdentityUpdatesRoleGrantedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IdentityUpdatesRoleGranted represents a RoleGranted event raised by the IdentityUpdates contract. +type IdentityUpdatesRoleGranted struct { + Role [32]byte + Account common.Address + Sender common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRoleGranted is a free log retrieval operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_IdentityUpdates *IdentityUpdatesFilterer) FilterRoleGranted(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*IdentityUpdatesRoleGrantedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _IdentityUpdates.contract.FilterLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return &IdentityUpdatesRoleGrantedIterator{contract: _IdentityUpdates.contract, event: "RoleGranted", logs: logs, sub: sub}, nil +} + +// WatchRoleGranted is a free log subscription operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_IdentityUpdates *IdentityUpdatesFilterer) WatchRoleGranted(opts *bind.WatchOpts, sink chan<- *IdentityUpdatesRoleGranted, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _IdentityUpdates.contract.WatchLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IdentityUpdatesRoleGranted) + if err := _IdentityUpdates.contract.UnpackLog(event, "RoleGranted", 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 +} + +// ParseRoleGranted is a log parse operation binding the contract event 0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d. +// +// Solidity: event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender) +func (_IdentityUpdates *IdentityUpdatesFilterer) ParseRoleGranted(log types.Log) (*IdentityUpdatesRoleGranted, error) { + event := new(IdentityUpdatesRoleGranted) + if err := _IdentityUpdates.contract.UnpackLog(event, "RoleGranted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IdentityUpdatesRoleRevokedIterator is returned from FilterRoleRevoked and is used to iterate over the raw logs and unpacked data for RoleRevoked events raised by the IdentityUpdates contract. +type IdentityUpdatesRoleRevokedIterator struct { + Event *IdentityUpdatesRoleRevoked // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IdentityUpdatesRoleRevokedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IdentityUpdatesRoleRevoked) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IdentityUpdatesRoleRevoked) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IdentityUpdatesRoleRevokedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IdentityUpdatesRoleRevokedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IdentityUpdatesRoleRevoked represents a RoleRevoked event raised by the IdentityUpdates contract. +type IdentityUpdatesRoleRevoked struct { + Role [32]byte + Account common.Address + Sender common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRoleRevoked is a free log retrieval operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_IdentityUpdates *IdentityUpdatesFilterer) FilterRoleRevoked(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*IdentityUpdatesRoleRevokedIterator, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _IdentityUpdates.contract.FilterLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return &IdentityUpdatesRoleRevokedIterator{contract: _IdentityUpdates.contract, event: "RoleRevoked", logs: logs, sub: sub}, nil +} + +// WatchRoleRevoked is a free log subscription operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_IdentityUpdates *IdentityUpdatesFilterer) WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- *IdentityUpdatesRoleRevoked, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { + + var roleRule []interface{} + for _, roleItem := range role { + roleRule = append(roleRule, roleItem) + } + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _IdentityUpdates.contract.WatchLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IdentityUpdatesRoleRevoked) + if err := _IdentityUpdates.contract.UnpackLog(event, "RoleRevoked", 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 +} + +// ParseRoleRevoked is a log parse operation binding the contract event 0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b. +// +// Solidity: event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender) +func (_IdentityUpdates *IdentityUpdatesFilterer) ParseRoleRevoked(log types.Log) (*IdentityUpdatesRoleRevoked, error) { + event := new(IdentityUpdatesRoleRevoked) + if err := _IdentityUpdates.contract.UnpackLog(event, "RoleRevoked", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IdentityUpdatesUnpausedIterator is returned from FilterUnpaused and is used to iterate over the raw logs and unpacked data for Unpaused events raised by the IdentityUpdates contract. +type IdentityUpdatesUnpausedIterator struct { + Event *IdentityUpdatesUnpaused // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IdentityUpdatesUnpausedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IdentityUpdatesUnpaused) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IdentityUpdatesUnpaused) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IdentityUpdatesUnpausedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IdentityUpdatesUnpausedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IdentityUpdatesUnpaused represents a Unpaused event raised by the IdentityUpdates contract. +type IdentityUpdatesUnpaused struct { + Account common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUnpaused is a free log retrieval operation binding the contract event 0x5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa. +// +// Solidity: event Unpaused(address account) +func (_IdentityUpdates *IdentityUpdatesFilterer) FilterUnpaused(opts *bind.FilterOpts) (*IdentityUpdatesUnpausedIterator, error) { + + logs, sub, err := _IdentityUpdates.contract.FilterLogs(opts, "Unpaused") + if err != nil { + return nil, err + } + return &IdentityUpdatesUnpausedIterator{contract: _IdentityUpdates.contract, event: "Unpaused", logs: logs, sub: sub}, nil +} + +// WatchUnpaused is a free log subscription operation binding the contract event 0x5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa. +// +// Solidity: event Unpaused(address account) +func (_IdentityUpdates *IdentityUpdatesFilterer) WatchUnpaused(opts *bind.WatchOpts, sink chan<- *IdentityUpdatesUnpaused) (event.Subscription, error) { + + logs, sub, err := _IdentityUpdates.contract.WatchLogs(opts, "Unpaused") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IdentityUpdatesUnpaused) + if err := _IdentityUpdates.contract.UnpackLog(event, "Unpaused", 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 +} + +// ParseUnpaused is a log parse operation binding the contract event 0x5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa. +// +// Solidity: event Unpaused(address account) +func (_IdentityUpdates *IdentityUpdatesFilterer) ParseUnpaused(log types.Log) (*IdentityUpdatesUnpaused, error) { + event := new(IdentityUpdatesUnpaused) + if err := _IdentityUpdates.contract.UnpackLog(event, "Unpaused", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IdentityUpdatesUpgradeAuthorizedIterator is returned from FilterUpgradeAuthorized and is used to iterate over the raw logs and unpacked data for UpgradeAuthorized events raised by the IdentityUpdates contract. +type IdentityUpdatesUpgradeAuthorizedIterator struct { + Event *IdentityUpdatesUpgradeAuthorized // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IdentityUpdatesUpgradeAuthorizedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IdentityUpdatesUpgradeAuthorized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IdentityUpdatesUpgradeAuthorized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IdentityUpdatesUpgradeAuthorizedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IdentityUpdatesUpgradeAuthorizedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IdentityUpdatesUpgradeAuthorized represents a UpgradeAuthorized event raised by the IdentityUpdates contract. +type IdentityUpdatesUpgradeAuthorized struct { + Upgrader common.Address + NewImplementation common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUpgradeAuthorized is a free log retrieval operation binding the contract event 0xd30e1d298bf814ea43d22b4ce8298062b08609cd67496483769d836157dd52fa. +// +// Solidity: event UpgradeAuthorized(address upgrader, address newImplementation) +func (_IdentityUpdates *IdentityUpdatesFilterer) FilterUpgradeAuthorized(opts *bind.FilterOpts) (*IdentityUpdatesUpgradeAuthorizedIterator, error) { + + logs, sub, err := _IdentityUpdates.contract.FilterLogs(opts, "UpgradeAuthorized") + if err != nil { + return nil, err + } + return &IdentityUpdatesUpgradeAuthorizedIterator{contract: _IdentityUpdates.contract, event: "UpgradeAuthorized", logs: logs, sub: sub}, nil +} + +// WatchUpgradeAuthorized is a free log subscription operation binding the contract event 0xd30e1d298bf814ea43d22b4ce8298062b08609cd67496483769d836157dd52fa. +// +// Solidity: event UpgradeAuthorized(address upgrader, address newImplementation) +func (_IdentityUpdates *IdentityUpdatesFilterer) WatchUpgradeAuthorized(opts *bind.WatchOpts, sink chan<- *IdentityUpdatesUpgradeAuthorized) (event.Subscription, error) { + + logs, sub, err := _IdentityUpdates.contract.WatchLogs(opts, "UpgradeAuthorized") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IdentityUpdatesUpgradeAuthorized) + if err := _IdentityUpdates.contract.UnpackLog(event, "UpgradeAuthorized", 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 +} + +// ParseUpgradeAuthorized is a log parse operation binding the contract event 0xd30e1d298bf814ea43d22b4ce8298062b08609cd67496483769d836157dd52fa. +// +// Solidity: event UpgradeAuthorized(address upgrader, address newImplementation) +func (_IdentityUpdates *IdentityUpdatesFilterer) ParseUpgradeAuthorized(log types.Log) (*IdentityUpdatesUpgradeAuthorized, error) { + event := new(IdentityUpdatesUpgradeAuthorized) + if err := _IdentityUpdates.contract.UnpackLog(event, "UpgradeAuthorized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// IdentityUpdatesUpgradedIterator is returned from FilterUpgraded and is used to iterate over the raw logs and unpacked data for Upgraded events raised by the IdentityUpdates contract. +type IdentityUpdatesUpgradedIterator struct { + Event *IdentityUpdatesUpgraded // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *IdentityUpdatesUpgradedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(IdentityUpdatesUpgraded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(IdentityUpdatesUpgraded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *IdentityUpdatesUpgradedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *IdentityUpdatesUpgradedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// IdentityUpdatesUpgraded represents a Upgraded event raised by the IdentityUpdates contract. +type IdentityUpdatesUpgraded struct { + Implementation common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUpgraded is a free log retrieval operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_IdentityUpdates *IdentityUpdatesFilterer) FilterUpgraded(opts *bind.FilterOpts, implementation []common.Address) (*IdentityUpdatesUpgradedIterator, error) { + + var implementationRule []interface{} + for _, implementationItem := range implementation { + implementationRule = append(implementationRule, implementationItem) + } + + logs, sub, err := _IdentityUpdates.contract.FilterLogs(opts, "Upgraded", implementationRule) + if err != nil { + return nil, err + } + return &IdentityUpdatesUpgradedIterator{contract: _IdentityUpdates.contract, event: "Upgraded", logs: logs, sub: sub}, nil +} + +// WatchUpgraded is a free log subscription operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_IdentityUpdates *IdentityUpdatesFilterer) WatchUpgraded(opts *bind.WatchOpts, sink chan<- *IdentityUpdatesUpgraded, implementation []common.Address) (event.Subscription, error) { + + var implementationRule []interface{} + for _, implementationItem := range implementation { + implementationRule = append(implementationRule, implementationItem) + } + + logs, sub, err := _IdentityUpdates.contract.WatchLogs(opts, "Upgraded", implementationRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(IdentityUpdatesUpgraded) + if err := _IdentityUpdates.contract.UnpackLog(event, "Upgraded", 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 +} + +// ParseUpgraded is a log parse operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_IdentityUpdates *IdentityUpdatesFilterer) ParseUpgraded(log types.Log) (*IdentityUpdatesUpgraded, error) { + event := new(IdentityUpdatesUpgraded) + if err := _IdentityUpdates.contract.UnpackLog(event, "Upgraded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/pkg/abis/nodes.go b/pkg/abis/nodes.go index 22a46a01..68343855 100644 --- a/pkg/abis/nodes.go +++ b/pkg/abis/nodes.go @@ -45,12 +45,34 @@ type NodesNodeWithId struct { // NodesMetaData contains all meta data concerning the Nodes contract. var NodesMetaData = &bind.MetaData{ ABI: "[{\"type\":\"constructor\",\"inputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"addNode\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"signingKeyPub\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"httpAddress\",\"type\":\"string\",\"internalType\":\"string\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"allNodes\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"tuple[]\",\"internalType\":\"structNodes.NodeWithId[]\",\"components\":[{\"name\":\"nodeId\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"node\",\"type\":\"tuple\",\"internalType\":\"structNodes.Node\",\"components\":[{\"name\":\"signingKeyPub\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"httpAddress\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"isHealthy\",\"type\":\"bool\",\"internalType\":\"bool\"}]}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"approve\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"balanceOf\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getApproved\",\"inputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getNode\",\"inputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structNodes.Node\",\"components\":[{\"name\":\"signingKeyPub\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"httpAddress\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"isHealthy\",\"type\":\"bool\",\"internalType\":\"bool\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"healthyNodes\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"tuple[]\",\"internalType\":\"structNodes.NodeWithId[]\",\"components\":[{\"name\":\"nodeId\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"node\",\"type\":\"tuple\",\"internalType\":\"structNodes.Node\",\"components\":[{\"name\":\"signingKeyPub\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"httpAddress\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"isHealthy\",\"type\":\"bool\",\"internalType\":\"bool\"}]}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isApprovedForAll\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"name\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"ownerOf\",\"inputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"renounceOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"safeTransferFrom\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"safeTransferFrom\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setApprovalForAll\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"approved\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"symbol\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"tokenURI\",\"inputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transferFrom\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"updateHealth\",\"inputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"isHealthy\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"updateHttpAddress\",\"inputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"httpAddress\",\"type\":\"string\",\"internalType\":\"string\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"Approval\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"approved\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"tokenId\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ApprovalForAll\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"operator\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"approved\",\"type\":\"bool\",\"indexed\":false,\"internalType\":\"bool\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"NodeUpdated\",\"inputs\":[{\"name\":\"nodeId\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"node\",\"type\":\"tuple\",\"indexed\":false,\"internalType\":\"structNodes.Node\",\"components\":[{\"name\":\"signingKeyPub\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"httpAddress\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"isHealthy\",\"type\":\"bool\",\"internalType\":\"bool\"}]}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Transfer\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"tokenId\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"ERC721IncorrectOwner\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ERC721InsufficientApproval\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ERC721InvalidApprover\",\"inputs\":[{\"name\":\"approver\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ERC721InvalidOperator\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ERC721InvalidOwner\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ERC721InvalidReceiver\",\"inputs\":[{\"name\":\"receiver\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ERC721InvalidSender\",\"inputs\":[{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"ERC721NonexistentToken\",\"inputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"OwnableInvalidOwner\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"}]},{\"type\":\"error\",\"name\":\"OwnableUnauthorizedAccount\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"}]}]", + Bin: "0x60806040526006805463ffffffff60a01b1916905534801561001f575f5ffd5b5033604051806040016040528060128152602001712c26aa28102737b2329027b832b930ba37b960711b815250604051806040016040528060048152602001630584d54560e41b815250815f908161007791906101ac565b50600161008482826101ac565b5050506001600160a01b0381166100b457604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b6100bd816100c3565b50610266565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b634e487b7160e01b5f52604160045260245ffd5b600181811c9082168061013c57607f821691505b60208210810361015a57634e487b7160e01b5f52602260045260245ffd5b50919050565b601f8211156101a757805f5260205f20601f840160051c810160208510156101855750805b601f840160051c820191505b818110156101a4575f8155600101610191565b50505b505050565b81516001600160401b038111156101c5576101c5610114565b6101d9816101d38454610128565b84610160565b6020601f82116001811461020b575f83156101f45750848201515b5f19600385901b1c1916600184901b1784556101a4565b5f84815260208120601f198516915b8281101561023a578785015182556020948501946001909201910161021a565b508482101561025757868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b612539806102735f395ff3fe608060405234801561000f575f5ffd5b5060043610610179575f3560e01c806370a08231116100d2578063a0eae81d11610088578063c87b56dd11610063578063c87b56dd14610326578063e985e9c514610339578063f2fde38b14610374575f5ffd5b8063a0eae81d146102d8578063a22cb46514610300578063b88d4fde14610313575f5ffd5b80638354196f116100b85780638354196f146102ac5780638da5cb5b146102bf57806395d89b41146102d0575f5ffd5b806370a0823114610283578063715018a6146102a4575f5ffd5b806317b5b840116101325780634f0f4aa91161010d5780634f0f4aa91461023d57806350d809931461025d5780636352211e14610270575f5ffd5b806317b5b8401461020f57806323b872dd1461021757806342842e0e1461022a575f5ffd5b806306fdde031161016257806306fdde03146101ba578063081812fc146101cf578063095ea7b3146101fa575f5ffd5b806301ffc9a71461017d57806302f6f1ba146101a5575b5f5ffd5b61019061018b366004611bd3565b610387565b60405190151581526020015b60405180910390f35b6101ad61046b565b60405161019c9190611c62565b6101c26106f7565b60405161019c9190611d00565b6101e26101dd366004611d12565b610786565b6040516001600160a01b03909116815260200161019c565b61020d610208366004611d44565b6107ad565b005b6101ad6107bc565b61020d610225366004611d6c565b610aec565b61020d610238366004611d6c565b610b9b565b61025061024b366004611d12565b610bb5565b60405161019c9190611da6565b61020d61026b366004611dfd565b610d28565b6101e261027e366004611d12565b610df6565b610296610291366004611e45565b610e00565b60405190815260200161019c565b61020d610e5e565b61020d6102ba366004611e6d565b610e71565b6006546001600160a01b03166101e2565b6101c2610ec6565b6102eb6102e6366004611e97565b610ed5565b60405163ffffffff909116815260200161019c565b61020d61030e366004611f17565b611069565b61020d610321366004611f6c565b611074565b6101c2610334366004611d12565b611092565b61019061034736600461204a565b6001600160a01b039182165f90815260056020908152604080832093909416825291909152205460ff1690565b61020d610382366004611e45565b611103565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd00000000000000000000000000000000000000000000000000000000148061041957507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b8061046557507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6006546060905f9074010000000000000000000000000000000000000000900463ffffffff1667ffffffffffffffff8111156104a9576104a9611f3f565b6040519080825280602002602001820160405280156104e257816020015b6104cf611b65565b8152602001906001900390816104c75790505b5090505f5b60065463ffffffff74010000000000000000000000000000000000000000909104811690821610156106f1575f61051f82600161209f565b61052a9060646120bb565b90506105528163ffffffff165f908152600260205260409020546001600160a01b0316151590565b156106e85760405180604001604052808263ffffffff16815260200160075f8463ffffffff1681526020019081526020015f206040518060600160405290815f8201805461059f906120e1565b80601f01602080910402602001604051908101604052809291908181526020018280546105cb906120e1565b80156106165780601f106105ed57610100808354040283529160200191610616565b820191905f5260205f20905b8154815290600101906020018083116105f957829003601f168201915b5050505050815260200160018201805461062f906120e1565b80601f016020809104026020016040519081016040528092919081815260200182805461065b906120e1565b80156106a65780601f1061067d576101008083540402835291602001916106a6565b820191905f5260205f20905b81548152906001019060200180831161068957829003601f168201915b50505091835250506002919091015460ff16151560209091015290528351849063ffffffff85169081106106dc576106dc61212c565b60200260200101819052505b506001016104e7565b50919050565b60605f8054610705906120e1565b80601f0160208091040260200160405190810160405280929190818152602001828054610731906120e1565b801561077c5780601f106107535761010080835404028352916020019161077c565b820191905f5260205f20905b81548152906001019060200180831161075f57829003601f168201915b5050505050905090565b5f61079082611159565b505f828152600460205260409020546001600160a01b0316610465565b6107b88282336111aa565b5050565b60605f805b60065474010000000000000000000000000000000000000000900463ffffffff16811015610854575f6107f5826001612159565b61080090606461216c565b5f818152600260205260409020549091506001600160a01b03161515801561083857505f8181526007602052604090206002015460ff165b1561084b578261084781612183565b9350505b506001016107c1565b505f8167ffffffffffffffff81111561086f5761086f611f3f565b6040519080825280602002602001820160405280156108a857816020015b610895611b65565b81526020019060019003908161088d5790505b5090505f805b60065463ffffffff7401000000000000000000000000000000000000000090910481169082161015610ae3575f6108e682600161209f565b6108f19060646120bb565b90506109198163ffffffff165f908152600260205260409020546001600160a01b0316151590565b801561093c575063ffffffff81165f9081526007602052604090206002015460ff165b15610ada5760405180604001604052808263ffffffff16815260200160075f8463ffffffff1681526020019081526020015f206040518060600160405290815f82018054610989906120e1565b80601f01602080910402602001604051908101604052809291908181526020018280546109b5906120e1565b8015610a005780601f106109d757610100808354040283529160200191610a00565b820191905f5260205f20905b8154815290600101906020018083116109e357829003601f168201915b50505050508152602001600182018054610a19906120e1565b80601f0160208091040260200160405190810160405280929190818152602001828054610a45906120e1565b8015610a905780601f10610a6757610100808354040283529160200191610a90565b820191905f5260205f20905b815481529060010190602001808311610a7357829003601f168201915b50505091835250506002919091015460ff16151560209091015290528451859085908110610ac057610ac061212c565b60200260200101819052508280610ad690612183565b9350505b506001016108ae565b50909392505050565b6006546001600160a01b03163314610b8b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f4f6e6c792074686520636f6e7472616374206f776e65722063616e207472616e60448201527f73666572204e6f6465206f776e6572736869700000000000000000000000000060648201526084015b60405180910390fd5b610b968383836111b7565b505050565b610b9683838360405180602001604052805f815250611074565b604080516060808201835280825260208201525f91810191909152610bd982611159565b505f8281526007602052604090819020815160608101909252805482908290610c01906120e1565b80601f0160208091040260200160405190810160405280929190818152602001828054610c2d906120e1565b8015610c785780601f10610c4f57610100808354040283529160200191610c78565b820191905f5260205f20905b815481529060010190602001808311610c5b57829003601f168201915b50505050508152602001600182018054610c91906120e1565b80601f0160208091040260200160405190810160405280929190818152602001828054610cbd906120e1565b8015610d085780601f10610cdf57610100808354040283529160200191610d08565b820191905f5260205f20905b815481529060010190602001808311610ceb57829003601f168201915b50505091835250506002919091015460ff16151560209091015292915050565b610d3183610df6565b6001600160a01b0316336001600160a01b031614610dd1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4f6e6c7920746865206f776e6572206f6620746865204e6f6465204e4654206360448201527f616e2075706461746520697473206874747020616464726573730000000000006064820152608401610b82565b5f838152600760205260409020600101610dec8284836121df565b50610b968361126c565b5f61046582611159565b5f6001600160a01b038216610e43576040517f89c62b640000000000000000000000000000000000000000000000000000000081525f6004820152602401610b82565b506001600160a01b03165f9081526003602052604090205490565b610e666112b6565b610e6f5f6112fc565b565b610e796112b6565b610e8282611159565b505f82815260076020526040902060020180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168215151790556107b88261126c565b606060018054610705906120e1565b5f610ede6112b6565b6006805474010000000000000000000000000000000000000000900463ffffffff16906014610f0c83612299565b91906101000a81548163ffffffff021916908363ffffffff160217905550505f6064600660149054906101000a900463ffffffff16610f4b91906120bb565b9050610f5d878263ffffffff16611365565b604051806060016040528087878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250505090825250604080516020601f8801819004810282018101909252868152918101919087908790819084018382808284375f920182905250938552505060016020938401525063ffffffff841681526007909152604090208151819061100190826122bd565b506020820151600182019061101690826122bd565b5060409190910151600290910180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905561105f63ffffffff821661126c565b9695505050505050565b6107b83383836113f8565b61107f848484610aec565b61108c33858585856114cd565b50505050565b606061109d82611159565b505f6110b360408051602081019091525f815290565b90505f8151116110d15760405180602001604052805f8152506110fc565b806110db84611671565b6040516020016110ec92919061238f565b6040516020818303038152906040525b9392505050565b61110b6112b6565b6001600160a01b03811661114d576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f6004820152602401610b82565b611156816112fc565b50565b5f818152600260205260408120546001600160a01b031680610465576040517f7e27328900000000000000000000000000000000000000000000000000000000815260048101849052602401610b82565b610b96838383600161170e565b6001600160a01b0382166111f9576040517f64a0ae920000000000000000000000000000000000000000000000000000000081525f6004820152602401610b82565b5f611205838333611861565b9050836001600160a01b0316816001600160a01b03161461108c576040517f64283d7b0000000000000000000000000000000000000000000000000000000081526001600160a01b0380861660048301526024820184905282166044820152606401610b82565b5f818152600760205260409081902090517f925a803604a97550dcfaba2eb298fb6e6f828340bdf9d467d2a34c50cfbba96a916112ab91849190612440565b60405180910390a150565b6006546001600160a01b03163314610e6f576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610b82565b600680546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6001600160a01b0382166113a7576040517f64a0ae920000000000000000000000000000000000000000000000000000000081525f6004820152602401610b82565b5f6113b383835f611861565b90506001600160a01b03811615610b96576040517f73c6ac6e0000000000000000000000000000000000000000000000000000000081525f6004820152602401610b82565b6001600160a01b038216611443576040517f5b08ba180000000000000000000000000000000000000000000000000000000081526001600160a01b0383166004820152602401610b82565b6001600160a01b038381165f8181526005602090815260408083209487168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b0383163b1561166a576040517f150b7a020000000000000000000000000000000000000000000000000000000081526001600160a01b0384169063150b7a02906115289088908890879087906004016124b2565b6020604051808303815f875af1925050508015611562575060408051601f3d908101601f1916820190925261155f918101906124e8565b60015b6115e2573d80801561158f576040519150601f19603f3d011682016040523d82523d5f602084013e611594565b606091505b5080515f036115da576040517f64a0ae920000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610b82565b805181602001fd5b7fffffffff0000000000000000000000000000000000000000000000000000000081167f150b7a020000000000000000000000000000000000000000000000000000000014611668576040517f64a0ae920000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610b82565b505b5050505050565b60605f61167d8361196b565b60010190505f8167ffffffffffffffff81111561169c5761169c611f3f565b6040519080825280601f01601f1916602001820160405280156116c6576020820181803683370190505b5090508181016020015b5f19017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a85049450846116d057509392505050565b808061172257506001600160a01b03821615155b1561181a575f61173184611159565b90506001600160a01b0383161580159061175d5750826001600160a01b0316816001600160a01b031614155b801561178e57506001600160a01b038082165f9081526005602090815260408083209387168352929052205460ff16155b156117d0576040517fa9fbf51f0000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602401610b82565b81156118185783856001600160a01b0316826001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b50505f90815260046020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b5f828152600260205260408120546001600160a01b039081169083161561188d5761188d818486611a4c565b6001600160a01b038116156118c7576118a85f855f5f61170e565b6001600160a01b0381165f90815260036020526040902080545f190190555b6001600160a01b038516156118f5576001600160a01b0385165f908152600360205260409020805460010190555b5f8481526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0389811691821790925591518793918516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4949350505050565b5f807a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106119b3577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef810000000083106119df576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106119fd57662386f26fc10000830492506010015b6305f5e1008310611a15576305f5e100830492506008015b6127108310611a2957612710830492506004015b60648310611a3b576064830492506002015b600a83106104655760010192915050565b611a57838383611ae2565b610b96576001600160a01b038316611a9e576040517f7e27328900000000000000000000000000000000000000000000000000000000815260048101829052602401610b82565b6040517f177e802f0000000000000000000000000000000000000000000000000000000081526001600160a01b038316600482015260248101829052604401610b82565b5f6001600160a01b03831615801590611b5d5750826001600160a01b0316846001600160a01b03161480611b3a57506001600160a01b038085165f9081526005602090815260408083209387168352929052205460ff165b80611b5d57505f828152600460205260409020546001600160a01b038481169116145b949350505050565b60405180604001604052805f63ffffffff168152602001611ba1604051806060016040528060608152602001606081526020015f151581525090565b905290565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114611156575f5ffd5b5f60208284031215611be3575f5ffd5b81356110fc81611ba6565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f815160608452611c306060850182611bee565b905060208301518482036020860152611c498282611bee565b9150506040830151151560408501528091505092915050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b82811015611cf4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0878603018452815163ffffffff81511686526020810151905060406020870152611cde6040870182611c1c565b9550506020938401939190910190600101611c88565b50929695505050505050565b602081525f6110fc6020830184611bee565b5f60208284031215611d22575f5ffd5b5035919050565b80356001600160a01b0381168114611d3f575f5ffd5b919050565b5f5f60408385031215611d55575f5ffd5b611d5e83611d29565b946020939093013593505050565b5f5f5f60608486031215611d7e575f5ffd5b611d8784611d29565b9250611d9560208501611d29565b929592945050506040919091013590565b602081525f6110fc6020830184611c1c565b5f5f83601f840112611dc8575f5ffd5b50813567ffffffffffffffff811115611ddf575f5ffd5b602083019150836020828501011115611df6575f5ffd5b9250929050565b5f5f5f60408486031215611e0f575f5ffd5b83359250602084013567ffffffffffffffff811115611e2c575f5ffd5b611e3886828701611db8565b9497909650939450505050565b5f60208284031215611e55575f5ffd5b6110fc82611d29565b80358015158114611d3f575f5ffd5b5f5f60408385031215611e7e575f5ffd5b82359150611e8e60208401611e5e565b90509250929050565b5f5f5f5f5f60608688031215611eab575f5ffd5b611eb486611d29565b9450602086013567ffffffffffffffff811115611ecf575f5ffd5b611edb88828901611db8565b909550935050604086013567ffffffffffffffff811115611efa575f5ffd5b611f0688828901611db8565b969995985093965092949392505050565b5f5f60408385031215611f28575f5ffd5b611f3183611d29565b9150611e8e60208401611e5e565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f5f5f5f60808587031215611f7f575f5ffd5b611f8885611d29565b9350611f9660208601611d29565b925060408501359150606085013567ffffffffffffffff811115611fb8575f5ffd5b8501601f81018713611fc8575f5ffd5b803567ffffffffffffffff811115611fe257611fe2611f3f565b604051601f19603f601f19601f8501160116810181811067ffffffffffffffff8211171561201257612012611f3f565b604052818152828201602001891015612029575f5ffd5b816020840160208301375f6020838301015280935050505092959194509250565b5f5f6040838503121561205b575f5ffd5b61206483611d29565b9150611e8e60208401611d29565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b63ffffffff818116838216019081111561046557610465612072565b63ffffffff81811683821602908116908181146120da576120da612072565b5092915050565b600181811c908216806120f557607f821691505b6020821081036106f1577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b8082018082111561046557610465612072565b808202811582820484141761046557610465612072565b5f5f19820361219457612194612072565b5060010190565b601f821115610b9657805f5260205f20601f840160051c810160208510156121c05750805b601f840160051c820191505b8181101561166a575f81556001016121cc565b67ffffffffffffffff8311156121f7576121f7611f3f565b61220b8361220583546120e1565b8361219b565b5f601f84116001811461223c575f85156122255750838201355b5f19600387901b1c1916600186901b17835561166a565b5f83815260208120601f198716915b8281101561226b578685013582556020948501946001909201910161224b565b5086821015612287575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b5f63ffffffff821663ffffffff81036122b4576122b4612072565b60010192915050565b815167ffffffffffffffff8111156122d7576122d7611f3f565b6122eb816122e584546120e1565b8461219b565b6020601f82116001811461231d575f83156123065750848201515b5f19600385901b1c1916600184901b17845561166a565b5f84815260208120601f198516915b8281101561234c578785015182556020948501946001909201910161232c565b508482101561236957868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b5f81518060208401855e5f93019283525090919050565b5f611b5d61239d8386612378565b84612378565b5f81546123af816120e1565b8085526001821680156123c9576001811461240357612437565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083166020870152602082151560051b8701019350612437565b845f5260205f205f5b8381101561242e5781546020828a01015260018201915060208101905061240c565b87016020019450505b50505092915050565b82815260406020820152606060408201525f61245f60a08301846123a3565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc083820301606084015261249681600186016123a3565b905060ff60028501541615156080840152809150509392505050565b6001600160a01b03851681526001600160a01b0384166020820152826040820152608060608201525f61105f6080830184611bee565b5f602082840312156124f8575f5ffd5b81516110fc81611ba656fea2646970667358221220666875a4755217bd116c1476c7d2d9e0e8228592ebb579176663769d172daabc64736f6c634300081c0033", } // NodesABI is the input ABI used to generate the binding from. // Deprecated: Use NodesMetaData.ABI instead. var NodesABI = NodesMetaData.ABI +// NodesBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use NodesMetaData.Bin instead. +var NodesBin = NodesMetaData.Bin + +// DeployNodes deploys a new Ethereum contract, binding an instance of Nodes to it. +func DeployNodes(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Nodes, error) { + parsed, err := NodesMetaData.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(NodesBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Nodes{NodesCaller: NodesCaller{contract: contract}, NodesTransactor: NodesTransactor{contract: contract}, NodesFilterer: NodesFilterer{contract: contract}}, nil +} + // Nodes is an auto generated Go binding around an Ethereum contract. type Nodes struct { NodesCaller // Read-only binding to the contract diff --git a/pkg/indexer/e2e_test.go b/pkg/indexer/e2e_test.go index c44d0e8f..2e4232d4 100644 --- a/pkg/indexer/e2e_test.go +++ b/pkg/indexer/e2e_test.go @@ -60,7 +60,7 @@ func TestStoreMessages(t *testing.T) { publisher := messagePublisher(t, ctx) defer cleanup() - message := testutils.RandomBytes(32) + message := testutils.RandomBytes(78) groupID := testutils.RandomGroupID() topic := topic.NewTopic(topic.TOPIC_KIND_GROUP_MESSAGES_V1, groupID[:]).Bytes() From 84c6aa235958e13bf44352c81232b3db4436362c Mon Sep 17 00:00:00 2001 From: Borja Aranda Date: Fri, 20 Dec 2024 17:56:18 +0100 Subject: [PATCH 7/8] updates all licenses to MIT --- contracts/script/DeployNodeRegistry.s.sol | 2 +- contracts/test/GroupMessage.t.sol | 2 +- contracts/test/IdentityUpdates.t.sol | 2 +- contracts/test/Nodes.sol | 2 +- contracts/test/utils/Utils.sol | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/script/DeployNodeRegistry.s.sol b/contracts/script/DeployNodeRegistry.s.sol index 210fdd31..84690866 100644 --- a/contracts/script/DeployNodeRegistry.s.sol +++ b/contracts/script/DeployNodeRegistry.s.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity 0.8.28; import {Script, console} from "forge-std/src/Script.sol"; diff --git a/contracts/test/GroupMessage.t.sol b/contracts/test/GroupMessage.t.sol index 72c1abf9..9becc55f 100644 --- a/contracts/test/GroupMessage.t.sol +++ b/contracts/test/GroupMessage.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity 0.8.28; import "forge-std/src/Vm.sol"; diff --git a/contracts/test/IdentityUpdates.t.sol b/contracts/test/IdentityUpdates.t.sol index 07691567..463ad895 100644 --- a/contracts/test/IdentityUpdates.t.sol +++ b/contracts/test/IdentityUpdates.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity 0.8.28; import "forge-std/src/Vm.sol"; diff --git a/contracts/test/Nodes.sol b/contracts/test/Nodes.sol index 0c9e7015..5512ba0b 100644 --- a/contracts/test/Nodes.sol +++ b/contracts/test/Nodes.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity 0.8.28; import {Test, console} from "forge-std/src/Test.sol"; diff --git a/contracts/test/utils/Utils.sol b/contracts/test/utils/Utils.sol index 3382b31c..fed61fd7 100644 --- a/contracts/test/utils/Utils.sol +++ b/contracts/test/utils/Utils.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT pragma solidity 0.8.28; import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; From 163f389cb2a48aac31b58c8eac6968a7b3857e09 Mon Sep 17 00:00:00 2001 From: Borja Aranda Date: Sun, 22 Dec 2024 14:36:37 +0100 Subject: [PATCH 8/8] generate config in human readable names --- contracts/README.md | 2 +- .../config/anvil_localnet/GroupMessages.json | 10 +++++++ .../anvil_localnet/IdentityUpdates.json | 10 +++++++ contracts/foundry.toml | 6 ++--- .../script/output/31337/GroupMessages.json | 10 ------- .../script/output/31337/IdentityUpdates.json | 10 ------- contracts/script/utils/Utils.sol | 26 ++++++++++++++++--- dev/baked/Dockerfile | 4 +-- dev/contracts/common | 4 +-- dev/local.env | 2 +- pkg/testutils/config.go | 4 +-- 11 files changed, 53 insertions(+), 35 deletions(-) create mode 100644 contracts/config/anvil_localnet/GroupMessages.json create mode 100644 contracts/config/anvil_localnet/IdentityUpdates.json delete mode 100644 contracts/script/output/31337/GroupMessages.json delete mode 100644 contracts/script/output/31337/IdentityUpdates.json diff --git a/contracts/README.md b/contracts/README.md index 75271f03..6594d2ce 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -76,7 +76,7 @@ The project includes deployer and upgrade scripts. ### Messages contracts -- Configure the environment by providing an `.env` file, with this content: +- Configure the environment by creating an `.env` file, with this content: ```shell ### Main configuration diff --git a/contracts/config/anvil_localnet/GroupMessages.json b/contracts/config/anvil_localnet/GroupMessages.json new file mode 100644 index 00000000..7ade0abb --- /dev/null +++ b/contracts/config/anvil_localnet/GroupMessages.json @@ -0,0 +1,10 @@ +{ + "addresses": { + "groupMessagesDeployer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "groupMessagesImpl": "0x0a17FabeA4633ce714F1Fa4a2dcA62C3bAc4758d", + "groupMessagesProxy": "0x3C1Cb427D20F15563aDa8C249E71db76d7183B6c", + "groupMessagesProxyAdmin": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + }, + "deploymentBlock": 65, + "latestUpgradeBlock": 71 +} \ No newline at end of file diff --git a/contracts/config/anvil_localnet/IdentityUpdates.json b/contracts/config/anvil_localnet/IdentityUpdates.json new file mode 100644 index 00000000..bcdaf689 --- /dev/null +++ b/contracts/config/anvil_localnet/IdentityUpdates.json @@ -0,0 +1,10 @@ +{ + "addresses": { + "identityUpdatesDeployer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "identityUpdatesImpl": "0x1343248Cbd4e291C6979e70a138f4c774e902561", + "identityUpdatesProxy": "0x22a9B82A6c3D2BFB68F324B2e8367f346Dd6f32a", + "identityUpdatesProxyAdmin": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + }, + "deploymentBlock": 67, + "latestUpgradeBlock": 67 +} \ No newline at end of file diff --git a/contracts/foundry.toml b/contracts/foundry.toml index 773ba6cd..f0d83ec0 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -13,9 +13,9 @@ remappings = [ "forge-std/=dependencies/forge-std-1.9.4/", ] fs_permissions = [ - { access = "read-write", path = "script/output/31337"}, - { access = "read-write", path = "script/output/11155111"}, - { access = "read-write", path = "script/output/241320161"} + { access = "read-write", path = "config/anvil_localnet"}, + { access = "read-write", path = "config/xmtp_testnet"}, + { access = "read-write", path = "config/unknown"} ] [soldeer] diff --git a/contracts/script/output/31337/GroupMessages.json b/contracts/script/output/31337/GroupMessages.json deleted file mode 100644 index d20f6cc2..00000000 --- a/contracts/script/output/31337/GroupMessages.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "addresses": { - "groupMessagesDeployer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "groupMessagesImpl": "0xB0f05d25e41FbC2b52013099ED9616f1206Ae21B", - "groupMessagesProxy": "0x5FeaeBfB4439F3516c74939A9D04e95AFE82C4ae", - "groupMessagesProxyAdmin": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" - }, - "deploymentBlock": 43, - "latestUpgradeBlock": 43 -} \ No newline at end of file diff --git a/contracts/script/output/31337/IdentityUpdates.json b/contracts/script/output/31337/IdentityUpdates.json deleted file mode 100644 index cd8f4b2a..00000000 --- a/contracts/script/output/31337/IdentityUpdates.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "addresses": { - "identityUpdatesDeployer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "identityUpdatesImpl": "0x976fcd02f7C4773dd89C309fBF55D5923B4c98a1", - "identityUpdatesProxy": "0x19cEcCd6942ad38562Ee10bAfd44776ceB67e923", - "identityUpdatesProxyAdmin": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" - }, - "deploymentBlock": 45, - "latestUpgradeBlock": 45 -} \ No newline at end of file diff --git a/contracts/script/utils/Utils.sol b/contracts/script/utils/Utils.sol index deac7579..12a48c8e 100644 --- a/contracts/script/utils/Utils.sol +++ b/contracts/script/utils/Utils.sol @@ -5,14 +5,21 @@ import "forge-std/src/Script.sol"; import "forge-std/src/StdJson.sol"; contract Utils is Script { + uint256 constant CHAIN_ID_ANVIL_LOCALNET = 31337; + uint256 constant CHAIN_ID_XMTP_TESTNET = 241320161; + + string constant OUTPUT_ANVIL_LOCALNET = "anvil_localnet"; + string constant OUTPUT_XMTP_TESTNET = "xmtp_testnet"; + string constant OUTPUT_UNKNOWN = "unknown"; + function readInput(string memory inputFileName) internal view returns (string memory) { string memory file = getInputPath(inputFileName); return vm.readFile(file); } function getInputPath(string memory inputFileName) internal view returns (string memory) { - string memory inputDir = string.concat(vm.projectRoot(), "/script/input/"); - string memory chainDir = string.concat(vm.toString(block.chainid), "/"); + string memory inputDir = string.concat(vm.projectRoot(), "/config/"); + string memory chainDir = string.concat(_resolveChainID(), "/"); string memory file = string.concat(inputFileName, ".json"); return string.concat(inputDir, chainDir, file); } @@ -28,9 +35,20 @@ contract Utils is Script { } function getOutputPath(string memory outputFileName) internal view returns (string memory) { - string memory outputDir = string.concat(vm.projectRoot(), "/script/output/"); - string memory chainDir = string.concat(vm.toString(block.chainid), "/"); + string memory outputDir = string.concat(vm.projectRoot(), "/config/"); + string memory chainDir = string.concat(_resolveChainID(), "/"); string memory outputFilePath = string.concat(outputDir, chainDir, outputFileName, ".json"); return outputFilePath; } + + function _resolveChainID() internal view returns (string memory) { + uint256 chainID = block.chainid; + if (chainID == CHAIN_ID_ANVIL_LOCALNET) { + return OUTPUT_ANVIL_LOCALNET; + } else if (chainID == CHAIN_ID_XMTP_TESTNET) { + return OUTPUT_XMTP_TESTNET; + } else { + return OUTPUT_UNKNOWN; + } + } } diff --git a/dev/baked/Dockerfile b/dev/baked/Dockerfile index 06e75b9a..dd09529c 100644 --- a/dev/baked/Dockerfile +++ b/dev/baked/Dockerfile @@ -29,8 +29,8 @@ RUN dev/docker/anvil-background && \ sleep 5 RUN echo "export XMTPD_CONTRACTS_NODES_ADDRESS="$(jq -r '.deployedTo' build/Nodes.json)"" >> contracts.env && \ - echo "export XMTPD_CONTRACTS_MESSAGES_ADDRESS="$(jq -r '.addresses.groupMessagesProxy' contracts/script/output/31337/GroupMessages.json)"" >> contracts.env && \ - echo "export XMTPD_CONTRACTS_IDENTITY_UPDATES_ADDRESS="$(jq -r '.addresses.identityUpdatesProxy' contracts/script/output/31337/IdentityUpdates.json)"" >> contracts.env + echo "export XMTPD_CONTRACTS_MESSAGES_ADDRESS="$(jq -r '.addresses.groupMessagesProxy' contracts/config/anvil_localnet/GroupMessages.json)"" >> contracts.env && \ + echo "export XMTPD_CONTRACTS_IDENTITY_UPDATES_ADDRESS="$(jq -r '.addresses.identityUpdatesProxy' contracts/config/anvil_localnet/IdentityUpdates.json)"" >> contracts.env # ACTUAL IMAGE ------------------------------------------------------- diff --git a/dev/contracts/common b/dev/contracts/common index a8035b21..4ab899ea 100644 --- a/dev/contracts/common +++ b/dev/contracts/common @@ -11,7 +11,7 @@ function forge_deploy_script() { fi echo -e "✅ GroupMessages contract deployed.\n" - cat script/output/31337/GroupMessages.json + cat config/anvil_localnet/GroupMessages.json echo -e "\n" ;; @@ -23,7 +23,7 @@ function forge_deploy_script() { fi echo -e "✅ IdentityUpdates contract deployed.\n" - cat script/output/31337/IdentityUpdates.json + cat config/anvil_localnet/IdentityUpdates.json echo -e "\n" ;; diff --git a/dev/local.env b/dev/local.env index b934bddc..f07ecaf4 100755 --- a/dev/local.env +++ b/dev/local.env @@ -3,7 +3,7 @@ source dev/contracts/.env # Anvil scripts output folder -ANVIL_SCRIPTS_OUTPUT=contracts/script/output/31337 +ANVIL_SCRIPTS_OUTPUT=contracts/config/anvil_localnet # DB Options export XMTPD_DB_WRITER_CONNECTION_STRING="postgres://postgres:xmtp@localhost:8765/postgres?sslmode=disable" diff --git a/pkg/testutils/config.go b/pkg/testutils/config.go index 42eccff8..af586c58 100644 --- a/pkg/testutils/config.go +++ b/pkg/testutils/config.go @@ -96,12 +96,12 @@ func GetContractsOptions(t *testing.T) config.ContractsOptions { RpcUrl: BLOCKCHAIN_RPC_URL, MessagesContractAddress: getProxyAddress( t, - path.Join(rootDir, "./contracts/script/output/31337/GroupMessages.json"), + path.Join(rootDir, "./contracts/config/anvil_localnet/GroupMessages.json"), ), NodesContractAddress: getDeployedTo(t, path.Join(rootDir, "./build/Nodes.json")), IdentityUpdatesContractAddress: getProxyAddress( t, - path.Join(rootDir, "./contracts/script/output/31337/IdentityUpdates.json"), + path.Join(rootDir, "./contracts/config/anvil_localnet/IdentityUpdates.json"), ), RefreshInterval: 100 * time.Millisecond, ChainID: 31337,