From b25b9138da7d2a97b5e14934fb4edb911bc7fa22 Mon Sep 17 00:00:00 2001 From: just-mitch <68168980+just-mitch@users.noreply.github.com> Date: Thu, 24 Oct 2024 05:04:29 -0400 Subject: [PATCH] chore: unstake the bond when the proof lands (#9363) If you claimed it, and the proof lands (from anyone) your bond is unstaked. --- l1-contracts/src/core/Rollup.sol | 11 ++++++- l1-contracts/test/Rollup.t.sol | 52 ++++++++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/l1-contracts/src/core/Rollup.sol b/l1-contracts/src/core/Rollup.sol index 9957010f9df..c6c7e5fd6c0 100644 --- a/l1-contracts/src/core/Rollup.sol +++ b/l1-contracts/src/core/Rollup.sol @@ -272,6 +272,10 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Leonidas, IRollup, ITestRollup { } } + if (proofClaim.epochToProve == getEpochForBlock(endBlockNumber)) { + PROOF_COMMITMENT_ESCROW.unstakeBond(proofClaim.bondProvider, proofClaim.bondAmount); + } + emit L2ProofVerified(endBlockNumber, _args[6]); } @@ -365,8 +369,13 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Leonidas, IRollup, ITestRollup { function getClaimableEpoch() external view override(IRollup) returns (Epoch) { Epoch epochToProve = getEpochToProve(); require( + // If the epoch has been claimed, it cannot be claimed again proofClaim.epochToProve != epochToProve - || (proofClaim.proposerClaimant == address(0) && proofClaim.epochToProve == Epoch.wrap(0)), + // Edge case for if no claim has been made yet. + // We know that the bondProvider is always set, + // Since otherwise the claimEpochProofRight would have reverted, + // because the zero address cannot have deposited funds into escrow. + || proofClaim.bondProvider == address(0), Errors.Rollup__ProofRightAlreadyClaimed() ); return epochToProve; diff --git a/l1-contracts/test/Rollup.t.sol b/l1-contracts/test/Rollup.t.sol index 715915ce77b..e2d653cae0f 100644 --- a/l1-contracts/test/Rollup.t.sol +++ b/l1-contracts/test/Rollup.t.sol @@ -201,10 +201,58 @@ contract RollupTest is DecoderBase { assertEq(epochToProve, signedQuote.quote.epochToProve, "Invalid epoch to prove"); assertEq(basisPointFee, signedQuote.quote.basisPointFee, "Invalid basis point fee"); assertEq(bondAmount, signedQuote.quote.bondAmount, "Invalid bond amount"); - // TODO #8573 - // This will be fixed with proper escrow assertEq(bondProvider, quote.prover, "Invalid bond provider"); assertEq(proposerClaimant, address(this), "Invalid proposer claimant"); + assertEq( + proofCommitmentEscrow.deposits(quote.prover), quote.bondAmount * 9, "Invalid escrow balance" + ); + } + + function testProofReleasesBond() public setUpFor("mixed_block_1") { + DecoderBase.Data memory data = load("mixed_block_1").block; + bytes memory header = data.header; + bytes32 archive = data.archive; + bytes32 blockHash = data.blockHash; + bytes32 proverId = bytes32(uint256(42)); + bytes memory body = data.body; + bytes32[] memory txHashes = new bytes32[](0); + + // We jump to the time of the block. (unless it is in the past) + vm.warp(max(block.timestamp, data.decodedHeader.globalVariables.timestamp)); + + rollup.propose(header, archive, blockHash, txHashes, signatures, body); + + quote.epochToProve = Epoch.wrap(1); + quote.validUntilSlot = Epoch.wrap(2).toSlots(); + signedQuote = _quoteToSignedQuote(quote); + rollup.claimEpochProofRight(signedQuote); + (bytes32 preArchive, bytes32 preBlockHash,) = rollup.blocks(0); + + assertEq( + proofCommitmentEscrow.deposits(quote.prover), quote.bondAmount * 9, "Invalid escrow balance" + ); + + _submitEpochProof(rollup, 1, preArchive, archive, preBlockHash, blockHash, proverId); + + assertEq( + proofCommitmentEscrow.deposits(quote.prover), quote.bondAmount * 10, "Invalid escrow balance" + ); + } + + function testMissingProofSlashesBond(uint256 slotsToJump) public setUpFor("mixed_block_1") { + // @note, this gives a an overflow if bounding to type(uint256).max + // Tracked by https://github.com/AztecProtocol/aztec-packages/issues/9362 + slotsToJump = + bound(slotsToJump, 2 * Constants.AZTEC_EPOCH_DURATION, 1e20 * Constants.AZTEC_EPOCH_DURATION); + _testBlock("mixed_block_1", false, 1); + rollup.claimEpochProofRight(signedQuote); + warpToL2Slot(slotsToJump); + rollup.prune(); + _testBlock("mixed_block_1", true, slotsToJump); + + assertEq( + proofCommitmentEscrow.deposits(quote.prover), 9 * quote.bondAmount, "Invalid escrow balance" + ); } function testClaimTwice() public setUpFor("mixed_block_1") {