Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions docs/docs-network/reference/changelog/v4.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,50 @@ description: TODO

## Breaking changes

### StakingAssetHandler refactored to simple token faucet

The `StakingAssetHandler` L1 contract has been significantly simplified. It no longer handles validator registration directly - instead it functions as a simple STK token faucet with ZKPassport sybil resistance.

**v3.0.0:**
```solidity
// Single call registered validator
stakingAssetHandler.addValidator(attester, merkleProof, zkPassportParams, publicKeyG1, publicKeyG2, signature);
```

**v4.0.0:**
```solidity
// Step 1: Claim STK tokens from faucet
stakingAssetHandler.claim(zkPassportParams);

// Step 2: Approve rollup to spend tokens
stakingAsset.approve(rollupAddress, amount);

// Step 3: Deposit into rollup (user chooses their own withdrawer)
rollup.deposit(attester, withdrawer, publicKeyG1, publicKeyG2, signature, moveWithLatestRollup);
```

**Removed functions:**
- `addValidator()` - replaced by `claim()` + direct rollup deposit
- `reenterExitedValidator()`
- `setValidatorsToFlush()`, `setMintInterval()`, `setDepositsPerMint()`, `setWithdrawer()`
- `setSkipMerkleCheck()`, `setDepositMerkleRoot()`

**New functions:**
- `claim(ProofVerificationParams)` - claim STK tokens with ZKPassport proof
- `setFaucetAmount(uint256)` - owner sets claim amount
- `resetNullifier(bytes32)` - owner can reset a nullifier

**CLI changes:**
```bash
# v3.0.0
aztec add-l1-validator --merkle-proof <proof>

# v4.0.0
aztec add-l1-validator --withdrawer-address <address>
```

**Migration**: Users must now call `claim()` to get STK tokens, then deposit into the rollup themselves. The `--merkle-proof` CLI flag is removed; add `--withdrawer-address` instead.

## Removed features

## New features
Expand Down
2 changes: 1 addition & 1 deletion l1-contracts/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ out = 'out'
libs = ['lib']
# NOTE!: This line defines the solc version used.
# It is downloaded by bootstrap.sh, but the version string here is parsed.
solc = "./solc-0.8.27"
solc = "./solc-0.8.30"
evm_version = 'prague'
optimizer = true
match_path = "test/**/*.t.sol"
Expand Down
2 changes: 1 addition & 1 deletion l1-contracts/lib/circuits
Submodule circuits updated 621 files
27 changes: 5 additions & 22 deletions l1-contracts/script/InternalGov.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,8 @@ contract GovScript is Test {
emit log_named_decimal_uint("\tMint Amount", feeAssetHandler.mintAmount(), 18);

emit log_named_address("# Staking Asset", address(stakingAsset));
emit log_named_uint("\tMint Interval ", stakingAssetHandler.mintInterval());
emit log_named_uint("\tDeposits Per Mint", stakingAssetHandler.depositsPerMint());
emit log_named_decimal_uint("\tFaucet Amount ", stakingAssetHandler.faucetAmount(), 18);
emit log_named_address("\tRollup ", address(stakingAssetHandler.getRollup()));
emit log_named_address("\tWithdrawer ", address(stakingAssetHandler.withdrawer()));

emit log_named_address("# Rollup", address(rollup));
uint256 baseFee = rollup.getManaBaseFeeAt(Timestamp.wrap(block.timestamp), true);
Expand Down Expand Up @@ -207,28 +205,13 @@ contract GovScript is Test {

// This should be called to update the staking asset handler config when the rollup is updated
function updateStakingAssetHandlerConfig() public {
uint256 mintInterval = 60 * 60 * 24;
uint256 depositsPerMint = 100;
uint256 newFaucetAmount = 1_000_000 * 1e18; // 1M STK
address amin = 0x3b218d0F26d15B36C715cB06c949210a0d630637;

// Update the deposits per mint if it differs
if (stakingAssetHandler.mintInterval() != mintInterval) {
// Update the faucet amount if it differs
if (stakingAssetHandler.faucetAmount() != newFaucetAmount) {
vm.startBroadcast(ME);
stakingAssetHandler.setMintInterval(mintInterval);
vm.stopBroadcast();
}

// Update the deposits per mint if it differs
if (stakingAssetHandler.depositsPerMint() != depositsPerMint) {
vm.startBroadcast(ME);
stakingAssetHandler.setDepositsPerMint(depositsPerMint);
vm.stopBroadcast();
}

// Update the withdrawer if it's not amin
if (stakingAssetHandler.withdrawer() != amin) {
vm.startBroadcast(ME);
stakingAssetHandler.setWithdrawer(amin);
stakingAssetHandler.setFaucetAmount(newFaucetAmount);
vm.stopBroadcast();
}

Expand Down
45 changes: 45 additions & 0 deletions l1-contracts/script/ProofSim.s.sol

Large diffs are not rendered by default.

31 changes: 13 additions & 18 deletions l1-contracts/script/StakingAssetHandler.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,51 +19,46 @@ import {StakingAssetHandler} from "../src/mock/StakingAssetHandler.sol";
import {FeeAssetHandler} from "../src/mock/FeeAssetHandler.sol";
import {Timestamp, Slot} from "@aztec/core/libraries/TimeLib.sol";
import {IStaking} from "@aztec/core/interfaces/IStaking.sol";
import {ZKPassportVerifier} from "@zkpassport/ZKPassportVerifier.sol";
import {ZKPassportRootVerifier as ZKPassportVerifier} from "@zkpassport/ZKPassportRootVerifier.sol";

// NOTE: The values below are for the testnet on sepolia, deployed initially with `v3` in December 2025.
contract StakingAssetHandlerScript is Test {
address internal constant ME = address(0xf8d7d601759CBcfB78044bA7cA9B0c0D6301A54f);
address internal constant ME = address(0xdfe19Da6a717b7088621d8bBB66be59F2d78e924);

string internal constant DOMAIN = "testnet.aztec.network";
string internal constant SCOPE = "personhood";

bytes32 public constant DEPOSIT_MERKLE_ROOT = bytes32(0);

ZKPassportVerifier internal constant zkPassportVerifier =
ZKPassportVerifier(0x0b05F45ff2F431a136eE8e708458286eC02b0d00);
ZKPassportVerifier(0x1D000001000EFD9a6371f4d90bB8920D5431c0D8);

TestERC20 public constant stakingAsset = TestERC20(0x6732CEDafCBF85Afa9B5C83f0385967840BBCe47);
IRegistry public constant registry = IRegistry(0xc2F24280F5c7F4897370dFDEb30f79Ded14f1c81);
TestERC20 public constant stakingAsset = TestERC20(0x5595cb9ED193cAc2C0Bc5393313bc6115817954B);
IRegistry public constant registry = IRegistry(0xA0BFb1B494FB49041e5c6e8c2C1BE09cD171c6Ba);

function setUp() public {}

function deploy() public {
address amin = 0x3b218d0F26d15B36C715cB06c949210a0d630637;
address koen = 0xEfDb4C5f3a2f04e0cb393725bCAE2DD675cC3718;

address[] memory isUnhinged = new address[](1);
isUnhinged[0] = amin;
address[] memory unhingedAddresses = new address[](2);
unhingedAddresses[0] = amin;
unhingedAddresses[1] = koen;

StakingAssetHandler.StakingAssetHandlerArgs memory stakingAssetHandlerArgs =
StakingAssetHandler.StakingAssetHandlerArgs({
owner: ME,
stakingAsset: address(stakingAsset),
registry: registry,
withdrawer: amin,
mintInterval: 60 * 60 * 24,
depositsPerMint: 1000,
depositMerkleRoot: DEPOSIT_MERKLE_ROOT,
faucetAmount: 1_000_000 * 1e18, // 1M STK
zkPassportVerifier: zkPassportVerifier,
unhinged: isUnhinged,
unhinged: unhingedAddresses,
domain: DOMAIN,
scope: SCOPE,
skipBindCheck: false, // DO NOT: skip bind check
skipMerkleCheck: true, // DO: skip merkle check
validatorsToFlush: 48
skipBindCheck: false // DO NOT: skip bind check
});

vm.startBroadcast(ME);
StakingAssetHandler stakingAssetHandler = new StakingAssetHandler(stakingAssetHandlerArgs);
stakingAsset.addMinter(address(stakingAssetHandler));
vm.stopBroadcast();

emit log_named_address("StakingAssetHandler deployed", address(stakingAssetHandler));
Expand Down
11 changes: 3 additions & 8 deletions l1-contracts/script/deploy/DeployAztecL1Contracts.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import {TestERC20} from "@aztec/mock/TestERC20.sol";

import {DateGatedRelayer} from "@aztec/periphery/DateGatedRelayer.sol";

import {ZKPassportVerifier} from "@zkpassport/ZKPassportVerifier.sol";
import {ZKPassportRootVerifier as ZKPassportVerifier} from "@zkpassport/ZKPassportRootVerifier.sol";

import {DeployRollupLib, RollupAddressInput, RollupAddressOutput} from "./DeployRollupLib.sol";
import {
Expand Down Expand Up @@ -230,18 +230,13 @@ contract DeployAztecL1Contracts is Script, Test {
owner: deployer,
stakingAsset: address(_output.stakingAsset),
registry: _output.registry,
withdrawer: AMIN,
validatorsToFlush: 16,
mintInterval: 60 * 60 * 24,
depositsPerMint: 10,
depositMerkleRoot: bytes32(0),
faucetAmount: 1_000_000 * 1e18, // 1M STK
zkPassportVerifier: ZKPassportVerifier(zkPassportVerifier),
unhinged: unhinged,
// Scopes
domain: zkConfig.domain,
scope: zkConfig.scope,
skipBindCheck: !isSepoliaTestChain, // Only skip bind check with mock verifier
skipMerkleCheck: true // DO: skip merkle check
skipBindCheck: !isSepoliaTestChain // Only skip bind check with mock verifier
})
);
TestERC20(address(_output.stakingAsset)).addMinter(address(_output.stakingAssetHandler));
Expand Down
Loading
Loading