diff --git a/src/contracts/StateProverPointer.sol b/src/contracts/StateProverPointer.sol index e48368c..243a386 100644 --- a/src/contracts/StateProverPointer.sol +++ b/src/contracts/StateProverPointer.sol @@ -62,6 +62,10 @@ contract StateProverPointer is IStateProverPointer, Ownable { _implementationAddress = _newImplementationAddress; _setCodeHash(_newImplementationAddress.codehash); + + emit ImplementationAddressSet( + newVersion, _newImplementationAddress, _newImplementationAddress.codehash, currentImplementationAddress + ); } function _setCodeHash(bytes32 _codeHash) internal { diff --git a/src/contracts/interfaces/IStateProverPointer.sol b/src/contracts/interfaces/IStateProverPointer.sol index 7e53bb1..63db210 100644 --- a/src/contracts/interfaces/IStateProverPointer.sol +++ b/src/contracts/interfaces/IStateProverPointer.sol @@ -8,6 +8,15 @@ pragma solidity 0.8.30; /// If the pointer's prover is updated, the new prover MUST have a higher IStateProver::version() than the old one. /// These pointers are always referred to by their address on their home chain. interface IStateProverPointer { + /// @notice Emitted when the pointer is set to a new implementation. + /// MUST be emitted when the pointer is set + event ImplementationAddressSet( + uint256 indexed newVersion, + address indexed newImplementationAddress, + bytes32 indexed newCodeHash, + address oldImplementationAddress + ); + /// @notice Return the code hash of the latest version of the prover. function implementationCodeHash() external view returns (bytes32); diff --git a/test/Receiver.ethereum.t.sol b/test/Receiver.ethereum.t.sol index 1bc5e9f..ffe648a 100644 --- a/test/Receiver.ethereum.t.sol +++ b/test/Receiver.ethereum.t.sol @@ -132,6 +132,10 @@ contract ReceiverTest is Test { StateProverPointer stateProverPointer = new StateProverPointer(owner); vm.prank(owner); + vm.expectEmit(); + emit IStateProverPointer.ImplementationAddressSet( + 1, address(parentToChildProver), address(parentToChildProver).codehash, address(0) + ); stateProverPointer.setImplementationAddress(address(parentToChildProver)); bytes32 message = 0x0000000000000000000000000000000000000000000000000000000074657374; // "test" diff --git a/test/Receiver.t.sol b/test/Receiver.t.sol index 2def15b..64806bd 100644 --- a/test/Receiver.t.sol +++ b/test/Receiver.t.sol @@ -108,6 +108,10 @@ contract ReceiverTest is Test { StateProverPointer stateProverPointer = new StateProverPointer(owner); vm.prank(owner); + vm.expectEmit(); + emit IStateProverPointer.ImplementationAddressSet( + 1, address(childToParentProver), address(childToParentProver).codehash, address(0) + ); stateProverPointer.setImplementationAddress(address(childToParentProver)); bytes32 message = 0x0000000000000000000000000000000000000000000000000000000074657374; // "test" @@ -184,6 +188,10 @@ contract ReceiverTest is Test { StateProverPointer stateProverPointer = new StateProverPointer(owner); vm.prank(owner); + vm.expectEmit(); + emit IStateProverPointer.ImplementationAddressSet( + 1, address(parentToChildProver), address(parentToChildProver).codehash, address(0) + ); stateProverPointer.setImplementationAddress(address(parentToChildProver)); bytes32 message = 0x0000000000000000000000000000000000000000000000000000000074657374; // "test" @@ -256,6 +264,10 @@ contract ReceiverTest is Test { StateProverPointer stateProverPointer = new StateProverPointer(owner); vm.prank(owner); + vm.expectEmit(); + emit IStateProverPointer.ImplementationAddressSet( + 1, address(childToParentProver), address(childToParentProver).codehash, address(0) + ); stateProverPointer.setImplementationAddress(address(childToParentProver)); bytes32 message = 0x0000000000000000000000000000000000000000000000000000000074657374; // "test" @@ -330,6 +342,10 @@ contract ReceiverTest is Test { StateProverPointer stateProverPointer = new StateProverPointer(owner); vm.prank(owner); + vm.expectEmit(); + emit IStateProverPointer.ImplementationAddressSet( + 1, address(childToParentProver), address(childToParentProver).codehash, address(0) + ); stateProverPointer.setImplementationAddress(address(childToParentProver)); uint256 expectedSlot = uint256(keccak256("eip7888.pointer.slot")) - 1; @@ -403,6 +419,10 @@ contract ReceiverTest is Test { StateProverPointer stateProverPointer = new StateProverPointer(owner); vm.prank(owner); + vm.expectEmit(); + emit IStateProverPointer.ImplementationAddressSet( + 1, address(childToParentProver), address(childToParentProver).codehash, address(0) + ); stateProverPointer.setImplementationAddress(address(childToParentProver)); uint256 expectedSlot = uint256(keccak256("eip7888.pointer.slot")) - 1; @@ -464,6 +484,10 @@ contract ReceiverTest is Test { address arbParentToChildProverPointerAddress; vm.prank(owner); + vm.expectEmit(); + emit IStateProverPointer.ImplementationAddressSet( + 1, address(childToParentProver), address(childToParentProver).codehash, address(0) + ); stateProverPointer.setImplementationAddress(address(childToParentProver)); // Update the Arbitrum Prover (ParentToChildProver) copy on OP chain { @@ -619,6 +643,10 @@ contract ReceiverTest is Test { StateProverPointer stateProverPointer = new StateProverPointer(owner); vm.prank(owner); + vm.expectEmit(); + emit IStateProverPointer.ImplementationAddressSet( + 1, address(childToParentProver), address(childToParentProver).codehash, address(0) + ); stateProverPointer.setImplementationAddress(address(childToParentProver)); uint256 expectedSlot = uint256(keccak256("eip7888.pointer.slot")) - 1; @@ -696,6 +724,10 @@ contract ReceiverTest is Test { address arbParentToChildProverPointerAddress; vm.prank(owner); + vm.expectEmit(); + emit IStateProverPointer.ImplementationAddressSet( + 1, address(childToParentProver), address(childToParentProver).codehash, address(0) + ); stateProverPointer.setImplementationAddress(address(childToParentProver)); // Update the Arbitrum Prover (ParentToChildProver) copy on ZKSync chain { @@ -847,6 +879,10 @@ contract ReceiverTest is Test { StateProverPointer stateProverPointer = new StateProverPointer(owner); vm.prank(owner); + vm.expectEmit(); + emit IStateProverPointer.ImplementationAddressSet( + 1, address(childToParentProver), address(childToParentProver).codehash, address(0) + ); stateProverPointer.setImplementationAddress(address(childToParentProver)); uint256 expectedSlot = uint256(keccak256("eip7888.pointer.slot")) - 1; @@ -924,6 +960,10 @@ contract ReceiverTest is Test { address arbParentToChildProverPointerAddress; vm.prank(owner); + vm.expectEmit(); + emit IStateProverPointer.ImplementationAddressSet( + 1, address(childToParentProver), address(childToParentProver).codehash, address(0) + ); stateProverPointer.setImplementationAddress(address(childToParentProver)); // Update the Arbitrum Prover (ParentToChildProver) copy on Linea chain { @@ -1075,6 +1115,10 @@ contract ReceiverTest is Test { StateProverPointer stateProverPointer = new StateProverPointer(owner); vm.prank(owner); + vm.expectEmit(); + emit IStateProverPointer.ImplementationAddressSet( + 1, address(childToParentProver), address(childToParentProver).codehash, address(0) + ); stateProverPointer.setImplementationAddress(address(childToParentProver)); uint256 expectedSlot = uint256(keccak256("eip7888.pointer.slot")) - 1; @@ -1152,6 +1196,10 @@ contract ReceiverTest is Test { address arbParentToChildProverPointerAddress; vm.prank(owner); + vm.expectEmit(); + emit IStateProverPointer.ImplementationAddressSet( + 1, address(childToParentProver), address(childToParentProver).codehash, address(0) + ); stateProverPointer.setImplementationAddress(address(childToParentProver)); // Update the Arbitrum Prover (ParentToChildProver) copy on Scroll chain { @@ -1309,6 +1357,10 @@ contract ReceiverTest is Test { StateProverPointer stateProverPointer = new StateProverPointer(owner); vm.prank(owner); + vm.expectEmit(); + emit IStateProverPointer.ImplementationAddressSet( + 1, address(parentToChildProver), address(parentToChildProver).codehash, address(0) + ); stateProverPointer.setImplementationAddress(address(parentToChildProver)); // Load the E2E proof data @@ -1365,6 +1417,10 @@ contract ReceiverTest is Test { StateProverPointer stateProverPointer = new StateProverPointer(owner); vm.prank(owner); + vm.expectEmit(); + emit IStateProverPointer.ImplementationAddressSet( + 1, address(parentToChildProver), address(parentToChildProver).codehash, address(0) + ); stateProverPointer.setImplementationAddress(address(parentToChildProver)); // Load the E2E proof data @@ -1443,6 +1499,10 @@ contract ReceiverTest is Test { StateProverPointer stateProverPointer = new StateProverPointer(owner); vm.prank(owner); + vm.expectEmit(); + emit IStateProverPointer.ImplementationAddressSet( + 1, address(parentToChildProver), address(parentToChildProver).codehash, address(0) + ); stateProverPointer.setImplementationAddress(address(parentToChildProver)); // Read the SMT proof data