diff --git a/packages/evm/contracts/adapters/Proofcast/ProofcastAdapter.sol b/packages/evm/contracts/adapters/Proofcast/ProofcastAdapter.sol index 382985a8..12e7784b 100644 --- a/packages/evm/contracts/adapters/Proofcast/ProofcastAdapter.sol +++ b/packages/evm/contracts/adapters/Proofcast/ProofcastAdapter.sol @@ -36,6 +36,8 @@ contract ProofcastAdapter is BlockHashAdapter, MessageIdCalculator, MessageHashC error InvalidSender(); error InvalidMessageId(uint256 actual, uint256 expected); error InvalidDestinationChainId(uint256 chainId); + error GracePeriodNotElapsed(); + error InvalidNewTeeSigner(); event TeeSignerChanged(address newAddress); event TeeSignerPendingChange(address newAddress, bytes attestation, uint256 gracePeriod); @@ -63,12 +65,17 @@ contract ProofcastAdapter is BlockHashAdapter, MessageIdCalculator, MessageHashC } } - function verifyEventAndStoreHash(bytes calldata statement, bytes memory signature) public { - if (teeAddressNew != address(0) && block.timestamp > teeAddressChangeGraceThreshold) { - teeAddress = teeAddressNew; - teeAddressNew = address(0); - emit TeeSignerChanged(teeAddress); - } + function applyNewTeeSigner() public { + if (block.timestamp < teeAddressChangeGraceThreshold) revert GracePeriodNotElapsed(); + if (teeAddressNew == address(0)) revert InvalidNewTeeSigner(); + + teeAddress = teeAddressNew; + teeAddressNew = address(0); + + emit TeeSignerChanged(teeAddress); + } + + function verifyEventAndStoreHash(bytes calldata statement, bytes memory signature) external { if (teeAddress == address(0)) revert InvalidTeeSigner(); if (ECDSA.recover(sha256(statement), signature) != teeAddress) revert InvalidSignature(); diff --git a/packages/evm/test/adapters/Proofcast/01_ProofcastAdapter.spec.ts b/packages/evm/test/adapters/Proofcast/01_ProofcastAdapter.spec.ts index fcbb325c..138496d9 100644 --- a/packages/evm/test/adapters/Proofcast/01_ProofcastAdapter.spec.ts +++ b/packages/evm/test/adapters/Proofcast/01_ProofcastAdapter.spec.ts @@ -197,6 +197,7 @@ describe("Proofcast adapter", () => { version: 0x00, protocolId: 0x00, chainId: Chains.Goerli, + privateKey: undefined, }) await expect(adapter.setTeeSigner(newEventAttestator.publicKey, attestation)) @@ -212,7 +213,6 @@ describe("Proofcast adapter", () => { await expect(adapter.verifyEventAndStoreHash(statement, signature)) .to.emit(adapter, "HashStored") .withArgs(ids[0], hashes[0]) - .and.not.to.emit(adapter, "TeeSignerChanged") expect(await adapter.teeAddress()).to.be.equal(previousAddress) @@ -222,14 +222,16 @@ describe("Proofcast adapter", () => { statement = newEventAttestator.getStatement(event) signature = newEventAttestator.sign(event) - await expect(adapter.verifyEventAndStoreHash(statement, signature)) + await expect(adapter.applyNewTeeSigner()) .to.emit(adapter, "TeeSignerChanged") .withArgs(newEventAttestator.address) + + await expect(adapter.verifyEventAndStoreHash(statement, signature)) .and.to.emit(adapter, "HashStored") .withArgs(ids[1], hashes[1]) }) - it("should wait another grace period when changing signer withing another grace period", async () => { + it("should wait another grace period when changing signer within another grace period", async () => { const { adapter, yaho, eventAttestator } = await loadFixture(setup) const previousAddress = await adapter.teeAddress() const eventAttestator1 = new ProofcastEventAttestator() @@ -250,7 +252,6 @@ describe("Proofcast adapter", () => { await expect(adapter.verifyEventAndStoreHash(statement, signature)) .to.emit(adapter, "HashStored") .withArgs(ids[1], hashes[1]) - .and.not.to.emit(adapter, "TeeSignerChanged") expect(await adapter.teeAddress()).to.be.equal(previousAddress) @@ -275,6 +276,8 @@ describe("Proofcast adapter", () => { statement = eventAttestator2.getStatement(event) signature = eventAttestator2.sign(event) + await expect(adapter.applyNewTeeSigner()).to.revertedWithCustomError(adapter, "GracePeriodNotElapsed") + await expect(adapter.verifyEventAndStoreHash(statement, signature)).to.be.revertedWithCustomError( adapter, "InvalidSignature", @@ -282,6 +285,8 @@ describe("Proofcast adapter", () => { await time.increase(gracePeriod / 2) + await expect(adapter.applyNewTeeSigner()).to.emit(adapter, "TeeSignerChanged") + await expect(adapter.verifyEventAndStoreHash(statement, signature)) .to.emit(adapter, "HashStored") .and.to.emit(adapter, "HashStored") diff --git a/packages/evm/test/adapters/Proofcast/ProofcastEventAttestator.ts b/packages/evm/test/adapters/Proofcast/ProofcastEventAttestator.ts index b2b7a764..0a085eb2 100644 --- a/packages/evm/test/adapters/Proofcast/ProofcastEventAttestator.ts +++ b/packages/evm/test/adapters/Proofcast/ProofcastEventAttestator.ts @@ -16,6 +16,7 @@ type Context = { version: number protocolId: number chainId: number + privateKey: string | undefined } const fromHex = (_0xString: string): Buffer => { @@ -36,13 +37,22 @@ class ProofcastEventAttestator { public chainId: Buffer public address: string public publicKey: string + public privateKey: string private signingKey: SigningKey - constructor({ version, protocolId, chainId }: Context = { version: 0x00, protocolId: 0x00, chainId: Chains.Goerli }) { + constructor( + { version, protocolId, chainId, privateKey }: Context = { + version: 0x00, + protocolId: 0x00, + chainId: Chains.Goerli, + privateKey: undefined, + }, + ) { this.version = Buffer.from([version]) this.chainId = Buffer.from(chainId.toString(16).padStart(64, "0"), "hex") this.protocolId = Buffer.from([protocolId]) - this.signingKey = new ethers.utils.SigningKey(crypto.randomBytes(32)) + this.privateKey = privateKey ? privateKey : crypto.randomBytes(32).toString("hex") + this.signingKey = new ethers.utils.SigningKey(Buffer.from(this.privateKey, "hex")) this.publicKey = this.signingKey.publicKey this.address = ethers.utils.computeAddress(this.publicKey) }