From cdb39a9df55cee914560cd798e48d24019d61f36 Mon Sep 17 00:00:00 2001 From: Eladio Date: Thu, 15 Jan 2026 12:22:02 +0100 Subject: [PATCH 01/51] Added hoodi addresses where applicable --- mainnet-contracts/script/DeployerHelper.s.sol | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/mainnet-contracts/script/DeployerHelper.s.sol b/mainnet-contracts/script/DeployerHelper.s.sol index ed39e42a..23137d75 100644 --- a/mainnet-contracts/script/DeployerHelper.s.sol +++ b/mainnet-contracts/script/DeployerHelper.s.sol @@ -14,6 +14,7 @@ abstract contract DeployerHelper is Script { // Chain IDs uint256 public mainnet = 1; uint256 public holesky = 17000; + uint256 public hoodi = 560048; uint256 public binance = 56; uint256 public base = 8453; uint256 public sepolia = 11155111; @@ -33,6 +34,9 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0 return 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0 + return 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; } else if (block.chainid == ape) { // https://apescan.io/address/0xb7d83623906AC3fa577F45B7D2b9D4BD26BC5d76 return 0xb7d83623906AC3fa577F45B7D2b9D4BD26BC5d76; @@ -125,6 +129,9 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/0x61A44645326846F9b5d9c6f91AD27C3aD28EA390 return 0x61A44645326846F9b5d9c6f91AD27C3aD28EA390; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/0x61A44645326846F9b5d9c6f91AD27C3aD28EA390 + return 0x61A44645326846F9b5d9c6f91AD27C3aD28EA390; } revert("Treasury not available for this chain"); @@ -137,6 +144,10 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/0xcAe751b75833ef09627549868A04E32679386e7C return 0xcAe751b75833ef09627549868A04E32679386e7C; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/??? + //return ???; + // @todo Find the address } revert("EigenSlasher not available for this chain"); @@ -149,6 +160,10 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/0x99c3E46E575df251149866285DdA7DAEba875B71 return 0x99c3E46E575df251149866285DdA7DAEba875B71; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/??? + // return ???; + // @todo Add address once deployed } revert("RestakingOperatorBeacon not available for this chain"); @@ -161,6 +176,9 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/0x4242424242424242424242424242424242424242 return 0x4242424242424242424242424242424242424242; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/0x00000000219ab540356cBB839Cbe05303d7705Fa + return 0x00000000219ab540356cBB839Cbe05303d7705Fa; } revert("BeaconDepositContract not available for this chain"); @@ -173,6 +191,10 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/0x0910310130d1c062DEF8B807528bdac80203BC66 return 0x0910310130d1c062DEF8B807528bdac80203BC66; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/??? + // return ???; + // @todo Add address once deployed } revert("GuardianModule not available for this chain"); @@ -185,6 +207,10 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/0x4B0542470935ed4b085C3AD1983E85f5623ABf89 return 0x4B0542470935ed4b085C3AD1983E85f5623ABf89; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/??? + // return ???; + // @todo Add address once deployed } revert("PufferModuleBeacon not available for this chain"); @@ -197,6 +223,9 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/0x30770d7E3e71112d7A6b7259542D1f680a70e315 return 0x30770d7E3e71112d7A6b7259542D1f680a70e315; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/0xcd1442415Fc5C29Aa848A49d2e232720BE07976c + return 0xcd1442415Fc5C29Aa848A49d2e232720BE07976c; } revert("EigenPodManager not available for this chain"); @@ -209,6 +238,9 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/0xA44151489861Fe9e3055d95adC98FbD462B948e7 return 0xA44151489861Fe9e3055d95adC98FbD462B948e7; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/0x867837a9722C512e0862d8c2E15b8bE220E8b87d + return 0x867837a9722C512e0862d8c2E15b8bE220E8b87d; } revert("DelegationManager not available for this chain"); @@ -221,6 +253,10 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/0x09BE86B01c1e32dCa2ebdEDb01cD5A3F798b80C5 return 0x09BE86B01c1e32dCa2ebdEDb01cD5A3F798b80C5; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/??? + // return ???; + // @todo Add address once deployed } revert("AVSContractsRegistry not available for this chain"); @@ -233,6 +269,10 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // Holesky Timelock: https://explorer.pops.one/address/0x829aF0B3d099a12F0aE1b806f466EF771E2C07F8 return 0x829aF0B3d099a12F0aE1b806f466EF771E2C07F8; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/??? + // return ???; + // @todo Add address once deployed } revert("Timelock not available for this chain"); @@ -245,6 +285,10 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/0xAcc1fb458a1317E886dB376Fc8141540537E68fE return 0xAcc1fb458a1317E886dB376Fc8141540537E68fE; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/??? + // return ???; + // @todo Add address once deployed } revert("RewardsCoordinator not available for this chain"); @@ -257,6 +301,9 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/0x3F1c547b21f65e10480dE3ad8E19fAAC46C95034 return 0x3F1c547b21f65e10480dE3ad8E19fAAC46C95034; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/0x3508A952176b3c15387C97BE809eaffB1982176a + return 0x3508A952176b3c15387C97BE809eaffB1982176a; } revert("stETH not available for this chain"); @@ -266,6 +313,9 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { return 0x8d09a4502Cc8Cf1547aD300E066060D043f6982D; } + if(block.chainid == hoodi) { + return 0x7E99eE3C66636DE415D2d7C880938F2f40f94De4; + } revert("WstETH not available for this chain"); } @@ -277,6 +327,9 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/0x7D704507b76571a51d9caE8AdDAbBFd0ba0e63d3 return 0x7D704507b76571a51d9caE8AdDAbBFd0ba0e63d3; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/0xF8a1a66130D614c7360e868576D5E59203475FE0 + return 0xF8a1a66130D614c7360e868576D5E59203475FE0; } revert("stETH strategy not available for this chain"); @@ -289,6 +342,9 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/0xdfB5f6CE42aAA7830E94ECFCcAd411beF4d4D5b6 return 0xdfB5f6CE42aAA7830E94ECFCcAd411beF4d4D5b6; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/0xeE45e76ddbEDdA2918b8C7E3035cd37Eab3b5D41 + return 0xeE45e76ddbEDdA2918b8C7E3035cd37Eab3b5D41; } revert("strategy manager not available for this chain"); @@ -301,6 +357,10 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/0x8e043ed3F06720615685D4978770Cd5C8fe90fe3 return 0x8e043ed3F06720615685D4978770Cd5C8fe90fe3; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/??? + // return ???; + // @todo Add address once deployed } revert("puffer oracle not available for this chain"); @@ -313,6 +373,9 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/0xA44151489861Fe9e3055d95adC98FbD462B948e7 return 0xA44151489861Fe9e3055d95adC98FbD462B948e7; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/0x867837a9722C512e0862d8c2E15b8bE220E8b87d + return 0x867837a9722C512e0862d8c2E15b8bE220E8b87d; } revert("eigen delegation manager not available for this chain"); @@ -325,6 +388,9 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/0x1d181cBd1825e9eBC6AD966878D555A7215FF4F0 return 0x1d181cBd1825e9eBC6AD966878D555A7215FF4F0; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/0x2387fD72C1DA19f6486B843F5da562679FbB4057 + return 0x2387fD72C1DA19f6486B843F5da562679FbB4057; } revert("WETH not available for this chain"); @@ -337,6 +403,9 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/0xc7cc160b58F8Bb0baC94b80847E2CF2800565C50 return 0xc7cc160b58F8Bb0baC94b80847E2CF2800565C50; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/0xfe56573178f1bcdf53F01A6E9977670dcBBD9186 + return 0xfe56573178f1bcdf53F01A6E9977670dcBBD9186; } revert("lido withdrawal queue not available for this chain"); @@ -352,6 +421,10 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/0x180a345906e42293dcAd5CCD9b0e1DB26aE0274e return 0x180a345906e42293dcAd5CCD9b0e1DB26aE0274e; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/??? + // return ???; + // @todo Add address once deployed } else if (block.chainid == binance) { // https://bscscan.com/address/0x8849e9eB8bb27c1916AfB17ee4dEcAd375916474 return 0x8849e9eB8bb27c1916AfB17ee4dEcAd375916474; @@ -377,6 +450,10 @@ abstract contract DeployerHelper is Script { // PufferVaultMock // https://sepolia.etherscan.io/address/0xd85D701A660a61D9737D05397612EF08be2cE62D return 0xd85D701A660a61D9737D05397612EF08be2cE62D; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/??? + // return ???; + // @todo Add address once deployed } revert("PufferVault not available for this chain"); @@ -389,6 +466,10 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/0x20377c306451140119C9967Ba6D0158a05b4eD07 return 0x20377c306451140119C9967Ba6D0158a05b4eD07; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/??? + // return ???; + // @todo Add address once deployed } revert("PufferModuleManager not available for this chain"); @@ -401,6 +482,10 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/0xB028194785178a94Fe608994A4d5AD84c285A640 return 0xB028194785178a94Fe608994A4d5AD84c285A640; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/??? + // return ???; + // @todo Add address once deployed } revert("ValidatorTicket not available for this chain"); @@ -413,6 +498,10 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/0xE00c79408B9De5BaD2FDEbB1688997a68eC988CD return 0xE00c79408B9De5BaD2FDEbB1688997a68eC988CD; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/??? + // return ???; + // @todo Add address once deployed } revert("PufferProtocol not available for this chain"); @@ -425,6 +514,10 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/TODO return address(0); // TODO + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/??? + // return ???; + // @todo Add address once deployed } revert("RestakingOperatorController not available for this chain"); @@ -494,6 +587,10 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/0xfe235A03d87FCBf94E91536955c8a6b1FF50A5C0 return 0xfe235A03d87FCBf94E91536955c8a6b1FF50A5C0; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/??? + // return ???; + // @todo Add address once deployed } revert("PufETHOFT not available for this chain"); @@ -503,6 +600,10 @@ abstract contract DeployerHelper is Script { if (block.chainid == sepolia) { // https://sepolia.etherscan.io/address/0xc0F1A1B26E7B3661c4875621883362CC48951c10 return 0xc0F1A1B26E7B3661c4875621883362CC48951c10; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/??? + // return ???; + // @todo Add address once deployed } revert("PufETHOFT not available for this chain"); @@ -544,6 +645,9 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0 return 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0 + return 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; } revert("Paymaster not available for this chain"); @@ -580,6 +684,9 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == holesky) { // https://holesky.etherscan.io/address/0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0 return 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0 + return 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; } else if (block.chainid == ape) { // https://apescan.io/address/0x36E3881Ff855c264045c22179b6fBc01430F97EC return 0x36E3881Ff855c264045c22179b6fBc01430F97EC; From db59be8d9c50d88411927061b8339d5926789f9a Mon Sep 17 00:00:00 2001 From: Eladio Date: Fri, 16 Jan 2026 13:17:43 +0100 Subject: [PATCH 02/51] Updated hoodi addresses and minor fixes --- mainnet-contracts/script/BaseScript.s.sol | 4 ++++ .../script/DeployEverything.s.sol | 2 +- mainnet-contracts/script/DeployPuffer.s.sol | 19 +++++++++++++++++-- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/mainnet-contracts/script/BaseScript.s.sol b/mainnet-contracts/script/BaseScript.s.sol index 374d85ed..b708db0b 100644 --- a/mainnet-contracts/script/BaseScript.s.sol +++ b/mainnet-contracts/script/BaseScript.s.sol @@ -44,6 +44,10 @@ abstract contract BaseScript is Script { return (block.chainid == 17000); } + function isHoodi() internal view returns (bool) { + return (block.chainid == 560048); + } + function isAnvil() internal view returns (bool) { return (block.chainid == 31337); } diff --git a/mainnet-contracts/script/DeployEverything.s.sol b/mainnet-contracts/script/DeployEverything.s.sol index a2e86236..8b5edee1 100644 --- a/mainnet-contracts/script/DeployEverything.s.sol +++ b/mainnet-contracts/script/DeployEverything.s.sol @@ -22,7 +22,7 @@ import { MockAeraVault } from "test/mocks/MockAeraVault.sol"; * @author Puffer Finance * @notice Deploys pufETH (upgrade it in test environment), Guardians, Oracle, Puffer, and sets up the access control * @dev Example on how to run the script - * forge script script/DeployEverything.s.sol:DeployEverything --rpc-url=$RPC_URL --sig 'run(address[] calldata, uint256)' "[$DEV_WALLET]" 1 --broadcast + * forge script script/DeployEverything.s.sol:DeployEverything --rpc-url=$RPC_URL --sig 'run(address[] calldata, uint256, address)' "[$DEV_WALLET]" 1 $DEV_WALLET --broadcast */ contract DeployEverything is BaseScript { address DAO; diff --git a/mainnet-contracts/script/DeployPuffer.s.sol b/mainnet-contracts/script/DeployPuffer.s.sol index ea294c78..27b7cf69 100644 --- a/mainnet-contracts/script/DeployPuffer.s.sol +++ b/mainnet-contracts/script/DeployPuffer.s.sol @@ -91,7 +91,7 @@ contract DeployPuffer is BaseScript { eigenSlasher = address(new EigenAllocationManagerMock()); treasury = address(1); operationsMultisig = address(2); - } else { + } else if (isHolesky()) { // Holesky https://github.com/Layr-Labs/eigenlayer-contracts?tab=readme-ov-file#current-testnet-deployment eigenPodManager = 0x30770d7E3e71112d7A6b7259542D1f680a70e315; delegationManager = 0xA44151489861Fe9e3055d95adC98FbD462B948e7; @@ -99,6 +99,16 @@ contract DeployPuffer is BaseScript { treasury = 0x61A44645326846F9b5d9c6f91AD27C3aD28EA390; rewardsCoordinator = 0xAcc1fb458a1317E886dB376Fc8141540537E68fE; operationsMultisig = 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; + } else if (isHoodi()) { + // Hoodi https://github.com/Layr-Labs/eigenlayer-contracts?tab=readme-ov-file#current-deployment-contracts + eigenPodManager = 0xcd1442415Fc5C29Aa848A49d2e232720BE07976c; + delegationManager = 0x867837a9722C512e0862d8c2E15b8bE220E8b87d; + eigenSlasher = 0xcAe751b75833ef09627549868A04E32679386e7C; // @todo Confirm EigenSlasher address + treasury = 0x61A44645326846F9b5d9c6f91AD27C3aD28EA390; + rewardsCoordinator = 0x29e8572678e0c272350aa0b4B8f304E47EBcd5e7; + operationsMultisig = 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; + } else { + revert("Deployment not configured for this chain"); } operationsCoordinator = new OperationsCoordinator(PufferOracleV2(oracle), address(accessManager), 500); // 500 BPS = 5% @@ -230,10 +240,15 @@ contract DeployPuffer is BaseScript { } // Holesky - if (block.chainid == 17000) { + if (isHolesky()) { return 0x4242424242424242424242424242424242424242; } + // Hoodi + if (isHoodi()) { + return 0x00000000219ab540356cBB839Cbe05303d7705Fa; + } + // Tests / local chain if (isAnvil()) { return address(new BeaconMock()); From 8417f78520f2946f9ab0ed980f4f661c3e8a2d00 Mon Sep 17 00:00:00 2001 From: Eladio Date: Fri, 16 Jan 2026 15:38:08 +0100 Subject: [PATCH 03/51] Updated addresses for hoodi --- mainnet-contracts/script/DeployPufETH.s.sol | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mainnet-contracts/script/DeployPufETH.s.sol b/mainnet-contracts/script/DeployPufETH.s.sol index 6309d523..c0d7dd12 100644 --- a/mainnet-contracts/script/DeployPufETH.s.sol +++ b/mainnet-contracts/script/DeployPufETH.s.sol @@ -253,6 +253,12 @@ contract DeployPufETH is BaseScript { lidoWithdrawalQueue = ILidoWithdrawalQueue(0xc7cc160b58F8Bb0baC94b80847E2CF2800565C50); stETHStrategy = IStrategy(0x7D704507b76571a51d9caE8AdDAbBFd0ba0e63d3); eigenStrategyManager = IEigenLayer(0xdfB5f6CE42aAA7830E94ECFCcAd411beF4d4D5b6); + } else if (isHoodi()) { + stETH = IStETH(address(0x3508A952176b3c15387C97BE809eaffB1982176a)); + weth = new WETH9(); + lidoWithdrawalQueue = ILidoWithdrawalQueue(0xfe56573178f1bcdf53F01A6E9977670dcBBD9186); + stETHStrategy = IStrategy(0xF8a1a66130D614c7360e868576D5E59203475FE0); + eigenStrategyManager = IEigenLayer(0xeE45e76ddbEDdA2918b8C7E3035cd37Eab3b5D41); } else { stETH = IStETH(address(new stETHMock())); weth = new WETH9(); From 73d9f793af2a84a39856350c9bbfab138a9f61b7 Mon Sep 17 00:00:00 2001 From: Eladio Date: Fri, 16 Jan 2026 17:39:32 +0100 Subject: [PATCH 04/51] Added hoodi addresses to DeployerHelper --- mainnet-contracts/script/DeployerHelper.s.sol | 59 ++++++++----------- 1 file changed, 24 insertions(+), 35 deletions(-) diff --git a/mainnet-contracts/script/DeployerHelper.s.sol b/mainnet-contracts/script/DeployerHelper.s.sol index 23137d75..3942c895 100644 --- a/mainnet-contracts/script/DeployerHelper.s.sol +++ b/mainnet-contracts/script/DeployerHelper.s.sol @@ -192,9 +192,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x0910310130d1c062DEF8B807528bdac80203BC66 return 0x0910310130d1c062DEF8B807528bdac80203BC66; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? - // return ???; - // @todo Add address once deployed + // https://hoodi.etherscan.io/address/0xF3654e122850Da267F4FA674BF96B671FF8EA216 + return 0xF3654e122850Da267F4FA674BF96B671FF8EA216; } revert("GuardianModule not available for this chain"); @@ -208,9 +207,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x4B0542470935ed4b085C3AD1983E85f5623ABf89 return 0x4B0542470935ed4b085C3AD1983E85f5623ABf89; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? - // return ???; - // @todo Add address once deployed + // https://hoodi.etherscan.io/address/0x6F2BDD64A7ba1Ca06784f58D2dBaF3f54a010F49 + return 0x6F2BDD64A7ba1Ca06784f58D2dBaF3f54a010F49; } revert("PufferModuleBeacon not available for this chain"); @@ -254,9 +252,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x09BE86B01c1e32dCa2ebdEDb01cD5A3F798b80C5 return 0x09BE86B01c1e32dCa2ebdEDb01cD5A3F798b80C5; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? - // return ???; - // @todo Add address once deployed + // https://hoodi.etherscan.io/address/0x66eb09811E1e46D60eD1421884E9FD76cbE555cA + return 0x66eb09811E1e46D60eD1421884E9FD76cbE555cA; } revert("AVSContractsRegistry not available for this chain"); @@ -270,9 +267,8 @@ abstract contract DeployerHelper is Script { // Holesky Timelock: https://explorer.pops.one/address/0x829aF0B3d099a12F0aE1b806f466EF771E2C07F8 return 0x829aF0B3d099a12F0aE1b806f466EF771E2C07F8; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? - // return ???; - // @todo Add address once deployed + // https://hoodi.etherscan.io/address/0xA7A7C971B320f8B9F9557D49Ad5d988A668acD86 + return 0xA7A7C971B320f8B9F9557D49Ad5d988A668acD86; } revert("Timelock not available for this chain"); @@ -358,9 +354,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x8e043ed3F06720615685D4978770Cd5C8fe90fe3 return 0x8e043ed3F06720615685D4978770Cd5C8fe90fe3; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? - // return ???; - // @todo Add address once deployed + // https://hoodi.etherscan.io/address/0x6d62a3520E47530cb9c1887b9C7FA4e6c2164027 + return 0x6d62a3520E47530cb9c1887b9C7FA4e6c2164027; } revert("puffer oracle not available for this chain"); @@ -389,8 +384,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x1d181cBd1825e9eBC6AD966878D555A7215FF4F0 return 0x1d181cBd1825e9eBC6AD966878D555A7215FF4F0; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0x2387fD72C1DA19f6486B843F5da562679FbB4057 - return 0x2387fD72C1DA19f6486B843F5da562679FbB4057; + // https://hoodi.etherscan.io/address/0x6CeA393234314e5c12d017F46a5cc9555c79fAee + return 0x6CeA393234314e5c12d017F46a5cc9555c79fAee; } revert("WETH not available for this chain"); @@ -422,9 +417,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x180a345906e42293dcAd5CCD9b0e1DB26aE0274e return 0x180a345906e42293dcAd5CCD9b0e1DB26aE0274e; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? - // return ???; - // @todo Add address once deployed + // https://hoodi.etherscan.io/address/0x9a86395B4c5B03a3D727A9037a122470adfA6F0e + return 0x9a86395B4c5B03a3D727A9037a122470adfA6F0e; } else if (block.chainid == binance) { // https://bscscan.com/address/0x8849e9eB8bb27c1916AfB17ee4dEcAd375916474 return 0x8849e9eB8bb27c1916AfB17ee4dEcAd375916474; @@ -451,9 +445,8 @@ abstract contract DeployerHelper is Script { // https://sepolia.etherscan.io/address/0xd85D701A660a61D9737D05397612EF08be2cE62D return 0xd85D701A660a61D9737D05397612EF08be2cE62D; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? - // return ???; - // @todo Add address once deployed + // https://hoodi.etherscan.io/address/0x5D5F97aAeb0c802C82B6E2d0C876CEc9C51cB1D1 + return 0x5D5F97aAeb0c802C82B6E2d0C876CEc9C51cB1D1; } revert("PufferVault not available for this chain"); @@ -467,9 +460,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x20377c306451140119C9967Ba6D0158a05b4eD07 return 0x20377c306451140119C9967Ba6D0158a05b4eD07; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? - // return ???; - // @todo Add address once deployed + // https://hoodi.etherscan.io/address/0x4a143618836f8bb84B328654f75d6C130500e375 + return 0x4a143618836f8bb84B328654f75d6C130500e375; } revert("PufferModuleManager not available for this chain"); @@ -483,9 +475,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0xB028194785178a94Fe608994A4d5AD84c285A640 return 0xB028194785178a94Fe608994A4d5AD84c285A640; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? - // return ???; - // @todo Add address once deployed + // https://hoodi.etherscan.io/address/0x34E70AcAEa2046F1c9E27894Ed8E05535A44DD41 + return 0x34E70AcAEa2046F1c9E27894Ed8E05535A44DD41; } revert("ValidatorTicket not available for this chain"); @@ -499,9 +490,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0xE00c79408B9De5BaD2FDEbB1688997a68eC988CD return 0xE00c79408B9De5BaD2FDEbB1688997a68eC988CD; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? - // return ???; - // @todo Add address once deployed + // https://hoodi.etherscan.io/address/0x7dE52e679e82395CB62C5B574A81cef637529fba + return 0x7dE52e679e82395CB62C5B574A81cef637529fba; } revert("PufferProtocol not available for this chain"); @@ -515,9 +505,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/TODO return address(0); // TODO } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? - // return ???; - // @todo Add address once deployed + // https://hoodi.etherscan.io/address/0x9C47BFa23E26d88b1F43c5EBA2CDb25fEF359ed1 + return 0x9C47BFa23E26d88b1F43c5EBA2CDb25fEF359ed1; } revert("RestakingOperatorController not available for this chain"); From a72ba47a2f86609dddad8d03c562efc1da20b4be Mon Sep 17 00:00:00 2001 From: Eladio Date: Fri, 16 Jan 2026 18:03:12 +0100 Subject: [PATCH 05/51] Added missing address --- mainnet-contracts/script/DeployerHelper.s.sol | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mainnet-contracts/script/DeployerHelper.s.sol b/mainnet-contracts/script/DeployerHelper.s.sol index 3942c895..670b256d 100644 --- a/mainnet-contracts/script/DeployerHelper.s.sol +++ b/mainnet-contracts/script/DeployerHelper.s.sol @@ -161,9 +161,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x99c3E46E575df251149866285DdA7DAEba875B71 return 0x99c3E46E575df251149866285DdA7DAEba875B71; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? - // return ???; - // @todo Add address once deployed + // https://hoodi.etherscan.io/address/0x9f9aa46c3b98aDDc1eEef87De25f986024f7C6Bb + return 0x9f9aa46c3b98aDDc1eEef87De25f986024f7C6Bb; } revert("RestakingOperatorBeacon not available for this chain"); From 14f6459d2a2026abbb689d1d33e72c432ee2d24c Mon Sep 17 00:00:00 2001 From: Eladio Date: Mon, 19 Jan 2026 16:27:03 +0100 Subject: [PATCH 06/51] Updated addresses and names (WIP) --- .github/workflows/mainnet-contracts.yml | 43 +++++----- l2-contracts/foundry.toml | 1 + mainnet-contracts/README.md | 23 +++--- mainnet-contracts/foundry.toml | 1 + mainnet-contracts/script/DeployerHelper.s.sol | 79 +++++++++---------- ...GenerateBLSKeysAndRegisterValidators.s.sol | 5 ++ .../PufferModuleManager.integration.t.sol | 24 +++--- ...fferModuleManagerSlasher.integration.t.sol | 18 ++--- .../ffi/PufferModuleManagerHoleskyFfi.t.sol | 32 ++++---- .../test/helpers/IntegrationTestHelper.sol | 12 +-- 10 files changed, 125 insertions(+), 113 deletions(-) diff --git a/.github/workflows/mainnet-contracts.yml b/.github/workflows/mainnet-contracts.yml index ddae9b63..8701c2bd 100644 --- a/.github/workflows/mainnet-contracts.yml +++ b/.github/workflows/mainnet-contracts.yml @@ -11,33 +11,33 @@ on: jobs: codespell: - name: Check for spelling errors - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Codespell - uses: codespell-project/actions-codespell@v2.0 - with: - path: mainnet-contracts - check_hidden: true - check_filenames: true - skip: "pnpm-lock.yaml" + name: Check for spelling errors + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Codespell + uses: codespell-project/actions-codespell@v2.0 + with: + path: mainnet-contracts + check_hidden: true + check_filenames: true + skip: "pnpm-lock.yaml" tests: runs-on: ubuntu-latest steps: - name: Cancel previous runs uses: styfle/cancel-workflow-action@0.12.1 - + - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - cache: 'yarn' + cache: "yarn" cache-dependency-path: yarn.lock node-version: 20 @@ -69,7 +69,7 @@ jobs: uses: stefanzweifel/git-auto-commit-action@v5 with: commit_message: "forge fmt" - file_pattern: '*.sol' + file_pattern: "*.sol" - name: List selectors working-directory: mainnet-contracts @@ -81,11 +81,11 @@ jobs: steps: - name: Cancel previous runs uses: styfle/cancel-workflow-action@0.12.1 - + - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - cache: 'yarn' + cache: "yarn" cache-dependency-path: yarn.lock node-version: 20 @@ -106,6 +106,7 @@ jobs: env: ETH_RPC_URL: ${{ secrets.ETH_RPC_URL }} HOLESKY_RPC_URL: ${{ secrets.HOLESKY_RPC_URL }} + HOODI_RPC_URL: ${{ secrets.HOODI_RPC_URL }} - name: "Upload coverage report to Codecov" uses: "codecov/codecov-action@v4" diff --git a/l2-contracts/foundry.toml b/l2-contracts/foundry.toml index 404dea24..ae2d846f 100644 --- a/l2-contracts/foundry.toml +++ b/l2-contracts/foundry.toml @@ -30,6 +30,7 @@ bracket_spacing = true [rpc_endpoints] mainnet="${ETH_RPC_URL}" holesky="${HOLESKY_RPC_URL}" +hoodi="${HOODI_RPC_URL}" [invariant] fail_on_revert=false diff --git a/mainnet-contracts/README.md b/mainnet-contracts/README.md index c5f055e8..876d098f 100644 --- a/mainnet-contracts/README.md +++ b/mainnet-contracts/README.md @@ -1,6 +1,7 @@ #

Puffer Vault

+ [![Website][Website-badge]][Website] [![Docs][docs-badge]][docs] - [![Discord][discord-badge]][discord] [![X][X-badge]][X] [![Foundry][foundry-badge]][foundry] +[![Discord][discord-badge]][discord] [![X][X-badge]][X] [![Foundry][foundry-badge]][foundry] [Website-badge]: https://img.shields.io/badge/WEBSITE-8A2BE2 [Website]: https://www.puffer.fi @@ -15,8 +16,8 @@ [foundry]: https://getfoundry.sh [foundry-badge]: https://img.shields.io/badge/Built%20with-Foundry-FFDB1C.svg +## Overview -## Overview Stakers can deposit ETH and mint the [pufETH nLRT](https://docs.puffer.fi/protocol/nlrt#pufeth) via the PufferVault contract, which serves as a redeemable receipt for their restaked ETH. If sufficient exit liquidity is available, stakers can reclaim their ETH from the PufferVault. Over time, the redeemable amount is expected to increase from [validator tickets](https://docs.puffer.fi/protocol/validator-tickets) and restaking rewards. In [contrast with conventional liquid staking tokens (LSTs)](https://docs.puffer.fi/protocol/nlrt#what-is-an-lst), pufETH can provide strictly more rewards for its holders. Not only does pufETH encompass PoS rewards and restaking rewards, but its value can accelerate quickly due to validator ticket sales. Furthermore, the PoS rewards for stakers are decoupled from the protocol validators' performance. @@ -27,17 +28,18 @@ pufETH is implemented as a reward-bearing ERC20 token, following [ERC4626](https Read more about pufETH and native Liquid Restaking Tokens (nLRTs) in the [Puffer Docs](https://docs.puffer.fi/protocol/nlrt#pufeth) website. - ## How pufETH Works + Stakers deposit ETH to the PufferVault contract to mint the pufETH nLRT. At the protocol's inception, pufETH's conversion rate is one-to-one, but is expected to increase over time. Assuming the protocol performs well, i.e., accrues more rewards than penalties, the amount of ETH reedamable for pufETH will increase. ### Calculating the Conversion Rate + The conversion rate can be calculated simply as: ``` conversion rate = (deposits + rewards - penalties) / pufETH supply ``` - + Where: - deposits and pufETH supply increase proportionally as stakers deposit ETH to mint pufETH, leaving the conversion rate unaffected. @@ -46,18 +48,17 @@ Where: - penalties accrue if validators are slashed on PoS for more than their 1 ETH collateral, which is [disincentivized behavior](https://docs.puffer.fi/protocol/validator-tickets#why--noop-incentives) and mitigated through [anti-slashing technology](https://docs.puffer.fi/technology/secure-signer). Penalties can also accrue if the restaking operator is slashed running AVSs, which is why Puffer is [restricting restaking operator participation](https://docs.puffer.fi/protocol/puffer-modules#restricting-reops) during its nascent stages. - - ## Contract addresses + - PufferVault (pufETH token): `0xD9A442856C234a39a81a089C06451EBAa4306a72` - PufferDepositor: `0x4aA799C5dfc01ee7d790e3bf1a7C2257CE1DcefF` - AccessManager: `0x8c1686069474410E6243425f4a10177a94EBEE11` - Timelock: `0x3C28B7c7Ba1A1f55c9Ce66b263B33B204f2126eA` -For more detailed information on the contract deployments (Mainnet, Holesky, etc) and the ABIs, please check the [Deployments and ACL](https://github.com/PufferFinance/Deployments-and-ACL/blob/main/docs/deployments/) repository. - +For more detailed information on the contract deployments (Mainnet, Holesky, Hoodi, etc) and the ABIs, please check the [Deployments and ACL](https://github.com/PufferFinance/Deployments-and-ACL/blob/main/docs/deployments/) repository. ## Audits + - BlockSec: [v1](./audits/BlockSec-pufETH-v1.pdf), [v2](https://github.com/PufferFinance/PufferPool/blob/polish-docs/docs/audits/Blocksec_audit_April2024.pdf) - SlowMist: [v1](./audits/SlowMist-pufETH-v1.pdf), v2 - Quantstamp: [v1](./audits/Quantstamp-pufETH-v1.pdf) @@ -66,21 +67,23 @@ For more detailed information on the contract deployments (Mainnet, Holesky, etc - Nethermind: [v2](https://github.com/NethermindEth/PublicAuditReports/blob/main/NM0202-FINAL_PUFFER.pdf) - Creed: [v2](https://github.com/PufferFinance/PufferPool/blob/polish-docs/docs/audits/Creed_Puffer_Finance_Audit_April2024.pdf) - # Tests Make sure you have access to a valid archive node RPC for ETH Mainnet (e.g. Infura) Installing dependencies and running tests can be executed running: + ``` ETH_RPC_URL=https://mainnet.infura.io/v3/YOUR_KEY forge test -vvvv ``` # Echidna + To install Echidna, see the instructions [here](https://github.com/crytic/echidna). To use Echidna, run the following command from the project's root: + ```bash forge install crytic/properties --no-commit echidna . --contract EchidnaPufferVaultV2 --config src/echidna/config.yaml ``` -For more information see the properties [README](https://github.com/crytic/properties/tree/main). +For more information see the properties [README](https://github.com/crytic/properties/tree/main). diff --git a/mainnet-contracts/foundry.toml b/mainnet-contracts/foundry.toml index 5718a887..74317cb3 100644 --- a/mainnet-contracts/foundry.toml +++ b/mainnet-contracts/foundry.toml @@ -44,6 +44,7 @@ bracket_spacing = true [rpc_endpoints] mainnet="${ETH_RPC_URL}" holesky="${HOLESKY_RPC_URL}" +hoodi="${HOODI_RPC_URL}" sepolia="${SEPOLIA_RPC_URL}" opsepolia ="${OP_SEPOLIA_RPC_URL}" diff --git a/mainnet-contracts/script/DeployerHelper.s.sol b/mainnet-contracts/script/DeployerHelper.s.sol index 670b256d..9c79f809 100644 --- a/mainnet-contracts/script/DeployerHelper.s.sol +++ b/mainnet-contracts/script/DeployerHelper.s.sol @@ -31,7 +31,7 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0xb7d83623906AC3fa577F45B7D2b9D4BD26BC5d76 return 0xb7d83623906AC3fa577F45B7D2b9D4BD26BC5d76; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0 return 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; } else if (block.chainid == hoodi) { @@ -80,7 +80,7 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x282A69142bac47855C3fbE1693FcC4bA3B4d5Ed6 return 0x282A69142bac47855C3fbE1693FcC4bA3B4d5Ed6; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0x82a44a6489936FFF841eecAF650Aa4D9708E4312 return 0x82a44a6489936FFF841eecAF650Aa4D9708E4312; } @@ -101,7 +101,7 @@ abstract contract DeployerHelper is Script { vm.label(implementation, contractName); console.log("Deployed", contractName, "at", implementation); - if (block.chainid == holesky) { + if (block.chainid == holesky) { // @DEPRECATED AccessManager(_getAccessManager()).execute( proxyTarget, abi.encodeCall(UUPSUpgradeable.upgradeToAndCall, (address(implementation), data)) ); @@ -126,7 +126,7 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x946Ae7b21de3B0793Bb469e263517481B74A6950 return 0x946Ae7b21de3B0793Bb469e263517481B74A6950; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0x61A44645326846F9b5d9c6f91AD27C3aD28EA390 return 0x61A44645326846F9b5d9c6f91AD27C3aD28EA390; } else if (block.chainid == hoodi) { @@ -141,13 +141,13 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0xD92145c07f8Ed1D392c1B88017934E301CC1c3Cd return 0xD92145c07f8Ed1D392c1B88017934E301CC1c3Cd; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0xcAe751b75833ef09627549868A04E32679386e7C return 0xcAe751b75833ef09627549868A04E32679386e7C; } else if (block.chainid == hoodi) { // https://hoodi.etherscan.io/address/??? //return ???; - // @todo Find the address + // TODO Find the address } revert("EigenSlasher not available for this chain"); @@ -157,7 +157,7 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x6756B856Dd3843C84249a6A31850cB56dB824c4B return 0x6756B856Dd3843C84249a6A31850cB56dB824c4B; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0x99c3E46E575df251149866285DdA7DAEba875B71 return 0x99c3E46E575df251149866285DdA7DAEba875B71; } else if (block.chainid == hoodi) { @@ -172,7 +172,7 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x00000000219ab540356cBB839Cbe05303d7705Fa return 0x00000000219ab540356cBB839Cbe05303d7705Fa; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0x4242424242424242424242424242424242424242 return 0x4242424242424242424242424242424242424242; } else if (block.chainid == hoodi) { @@ -187,7 +187,7 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x628b183F248a142A598AA2dcCCD6f7E480a7CcF2 return 0x628b183F248a142A598AA2dcCCD6f7E480a7CcF2; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0x0910310130d1c062DEF8B807528bdac80203BC66 return 0x0910310130d1c062DEF8B807528bdac80203BC66; } else if (block.chainid == hoodi) { @@ -202,7 +202,7 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0xdd38A5a7789C74fc7F64556fc772343658EEBb04 return 0xdd38A5a7789C74fc7F64556fc772343658EEBb04; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0x4B0542470935ed4b085C3AD1983E85f5623ABf89 return 0x4B0542470935ed4b085C3AD1983E85f5623ABf89; } else if (block.chainid == hoodi) { @@ -217,7 +217,7 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x91E677b07F7AF907ec9a428aafA9fc14a0d3A338 return 0x91E677b07F7AF907ec9a428aafA9fc14a0d3A338; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0x30770d7E3e71112d7A6b7259542D1f680a70e315 return 0x30770d7E3e71112d7A6b7259542D1f680a70e315; } else if (block.chainid == hoodi) { @@ -232,7 +232,7 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A return 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0xA44151489861Fe9e3055d95adC98FbD462B948e7 return 0xA44151489861Fe9e3055d95adC98FbD462B948e7; } else if (block.chainid == hoodi) { @@ -247,7 +247,7 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x1565E55B63675c703fcC3778BD33eA97F7bE882F return 0x1565E55B63675c703fcC3778BD33eA97F7bE882F; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0x09BE86B01c1e32dCa2ebdEDb01cD5A3F798b80C5 return 0x09BE86B01c1e32dCa2ebdEDb01cD5A3F798b80C5; } else if (block.chainid == hoodi) { @@ -262,7 +262,7 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // Mainnet Timelock: https://etherscan.io/address/0x3C28B7c7Ba1A1f55c9Ce66b263B33B204f2126eA return 0x3C28B7c7Ba1A1f55c9Ce66b263B33B204f2126eA; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // Holesky Timelock: https://explorer.pops.one/address/0x829aF0B3d099a12F0aE1b806f466EF771E2C07F8 return 0x829aF0B3d099a12F0aE1b806f466EF771E2C07F8; } else if (block.chainid == hoodi) { @@ -277,13 +277,12 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x7750d328b314EfFa365A0402CcfD489B80B0adda return 0x7750d328b314EfFa365A0402CcfD489B80B0adda; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0xAcc1fb458a1317E886dB376Fc8141540537E68fE return 0xAcc1fb458a1317E886dB376Fc8141540537E68fE; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? - // return ???; - // @todo Add address once deployed + // https://hoodi.etherscan.io/address/0x29e8572678e0c272350aa0b4B8f304E47EBcd5e7 + return 0x29e8572678e0c272350aa0b4B8f304E47EBcd5e7; } revert("RewardsCoordinator not available for this chain"); @@ -293,7 +292,7 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84 return 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0x3F1c547b21f65e10480dE3ad8E19fAAC46C95034 return 0x3F1c547b21f65e10480dE3ad8E19fAAC46C95034; } else if (block.chainid == hoodi) { @@ -319,7 +318,7 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x93c4b944D05dfe6df7645A86cd2206016c51564D return 0x93c4b944D05dfe6df7645A86cd2206016c51564D; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0x7D704507b76571a51d9caE8AdDAbBFd0ba0e63d3 return 0x7D704507b76571a51d9caE8AdDAbBFd0ba0e63d3; } else if (block.chainid == hoodi) { @@ -334,7 +333,7 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x858646372CC42E1A627fcE94aa7A7033e7CF075A return 0x858646372CC42E1A627fcE94aa7A7033e7CF075A; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0xdfB5f6CE42aAA7830E94ECFCcAd411beF4d4D5b6 return 0xdfB5f6CE42aAA7830E94ECFCcAd411beF4d4D5b6; } else if (block.chainid == hoodi) { @@ -349,7 +348,7 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x0BE2aE0edbeBb517541DF217EF0074FC9a9e994f return 0x0BE2aE0edbeBb517541DF217EF0074FC9a9e994f; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0x8e043ed3F06720615685D4978770Cd5C8fe90fe3 return 0x8e043ed3F06720615685D4978770Cd5C8fe90fe3; } else if (block.chainid == hoodi) { @@ -364,7 +363,7 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A return 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0xA44151489861Fe9e3055d95adC98FbD462B948e7 return 0xA44151489861Fe9e3055d95adC98FbD462B948e7; } else if (block.chainid == hoodi) { @@ -379,7 +378,7 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 return 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0x1d181cBd1825e9eBC6AD966878D555A7215FF4F0 return 0x1d181cBd1825e9eBC6AD966878D555A7215FF4F0; } else if (block.chainid == hoodi) { @@ -394,7 +393,7 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x889edC2eDab5f40e902b864aD4d7AdE8E412F9B1 return 0x889edC2eDab5f40e902b864aD4d7AdE8E412F9B1; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0xc7cc160b58F8Bb0baC94b80847E2CF2800565C50 return 0xc7cc160b58F8Bb0baC94b80847E2CF2800565C50; } else if (block.chainid == hoodi) { @@ -412,7 +411,7 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == mainnet) { // https://etherscan.io/address/0x8c1686069474410E6243425f4a10177a94EBEE11 return 0x8c1686069474410E6243425f4a10177a94EBEE11; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0x180a345906e42293dcAd5CCD9b0e1DB26aE0274e return 0x180a345906e42293dcAd5CCD9b0e1DB26aE0274e; } else if (block.chainid == hoodi) { @@ -436,7 +435,7 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0xD9A442856C234a39a81a089C06451EBAa4306a72 return 0xD9A442856C234a39a81a089C06451EBAa4306a72; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0x9196830bB4c05504E0A8475A0aD566AceEB6BeC9 return 0x9196830bB4c05504E0A8475A0aD566AceEB6BeC9; } else if (block.chainid == sepolia) { @@ -455,7 +454,7 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x9E1E4fCb49931df5743e659ad910d331735C3860 return 0x9E1E4fCb49931df5743e659ad910d331735C3860; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0x20377c306451140119C9967Ba6D0158a05b4eD07 return 0x20377c306451140119C9967Ba6D0158a05b4eD07; } else if (block.chainid == hoodi) { @@ -470,7 +469,7 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x7D26AD6F6BA9D6bA1de0218Ae5e20CD3a273a55A return 0x7D26AD6F6BA9D6bA1de0218Ae5e20CD3a273a55A; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0xB028194785178a94Fe608994A4d5AD84c285A640 return 0xB028194785178a94Fe608994A4d5AD84c285A640; } else if (block.chainid == hoodi) { @@ -485,7 +484,7 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0xf7b6B32492c2e13799D921E84202450131bd238B return 0xf7b6B32492c2e13799D921E84202450131bd238B; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0xE00c79408B9De5BaD2FDEbB1688997a68eC988CD return 0xE00c79408B9De5BaD2FDEbB1688997a68eC988CD; } else if (block.chainid == hoodi) { @@ -500,9 +499,9 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x953b4113716CE71596F7Ba6B0E75050c25c493c1 return 0x953b4113716CE71596F7Ba6B0E75050c25c493c1; - } else if (block.chainid == holesky) { - // https://holesky.etherscan.io/address/TODO - return address(0); // TODO + } else if (block.chainid == holesky) { // @DEPRECATED + // https://holesky.etherscan.io/address/- + return address(0); } else if (block.chainid == hoodi) { // https://hoodi.etherscan.io/address/0x9C47BFa23E26d88b1F43c5EBA2CDb25fEF359ed1 return 0x9C47BFa23E26d88b1F43c5EBA2CDb25fEF359ed1; @@ -572,13 +571,13 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0xa4931a9F9Aaf79057334371D6f62164743f97b18 return 0xa4931a9F9Aaf79057334371D6f62164743f97b18; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0xfe235A03d87FCBf94E91536955c8a6b1FF50A5C0 return 0xfe235A03d87FCBf94E91536955c8a6b1FF50A5C0; } else if (block.chainid == hoodi) { // https://hoodi.etherscan.io/address/??? // return ???; - // @todo Add address once deployed + // TODO Add address once deployed } revert("PufETHOFT not available for this chain"); @@ -591,7 +590,7 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == hoodi) { // https://hoodi.etherscan.io/address/??? // return ???; - // @todo Add address once deployed + // TODO Add address once deployed } revert("PufETHOFT not available for this chain"); @@ -604,7 +603,7 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == base) { // https://basescan.org/address/0x1a44076050125825900e736c501f859c50fE728c return 0x1a44076050125825900e736c501f859c50fE728c; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0x6EDCE65403992e310A62460808c4b910D972f10f return 0x6EDCE65403992e310A62460808c4b910D972f10f; } else if (block.chainid == sepolia) { @@ -616,7 +615,7 @@ abstract contract DeployerHelper is Script { } function _getLayerZeroDestinationEID() internal view returns (uint32) { - if (block.chainid == holesky) { + if (block.chainid == holesky) { // @DEPRECATED // https://docs.layerzero.network/v2/deployments/deployed-contracts return 40217; } else if (block.chainid == sepolia) { @@ -630,7 +629,7 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x65d2dd7A66a2733a36559fE900A236280A05FBD6 return 0x65d2dd7A66a2733a36559fE900A236280A05FBD6; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0 return 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; } else if (block.chainid == hoodi) { @@ -669,7 +668,7 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0xC0896ab1A8cae8c2C1d27d011eb955Cca955580d return 0xC0896ab1A8cae8c2C1d27d011eb955Cca955580d; - } else if (block.chainid == holesky) { + } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0 return 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; } else if (block.chainid == hoodi) { diff --git a/mainnet-contracts/script/GenerateBLSKeysAndRegisterValidators.s.sol b/mainnet-contracts/script/GenerateBLSKeysAndRegisterValidators.s.sol index 649ac165..414e4f96 100644 --- a/mainnet-contracts/script/GenerateBLSKeysAndRegisterValidators.s.sol +++ b/mainnet-contracts/script/GenerateBLSKeysAndRegisterValidators.s.sol @@ -43,6 +43,11 @@ contract GenerateBLSKeysAndRegisterValidators is Script { protocolAddress = 0xE00c79408B9De5BaD2FDEbB1688997a68eC988CD; pufferProtocol = PufferProtocol(protocolAddress); forkVersion = "0x01017000"; + } else if (block.chainid == 560048) { + // Hoodi + protocolAddress = 0x7dE52e679e82395CB62C5B574A81cef637529fba; + pufferProtocol = PufferProtocol(protocolAddress); + forkVersion = "0x10000910"; } else if (block.chainid == 1) { // Mainnet protocolAddress = 0xf7b6B32492c2e13799D921E84202450131bd238B; diff --git a/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol b/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol index 7fd56baf..8a53f474 100644 --- a/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol +++ b/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol @@ -26,12 +26,14 @@ contract PufferModuleManagerIntegrationTest is IntegrationTestHelper { uint256[] privKeys; - address EIGEN_DA_REGISTRY_COORDINATOR_HOLESKY = 0x53012C69A189cfA2D9d29eb6F19B32e0A2EA3490; - address EIGEN_DA_SERVICE_MANAGER = 0xD4A7E1Bd8015057293f0D0A557088c286942e84b; + address EIGEN_DA_REGISTRY_COORDINATOR_HOODI = 0x53012C69A189cfA2D9d29eb6F19B32e0A2EA3490; // TODO Change + address EIGEN_DA_SERVICE_MANAGER = 0xD4A7E1Bd8015057293f0D0A557088c286942e84b; // TODO Change // IAVSDirectory public avsDirectory = IAVSDirectory(0x055733000064333CaDDbC92763c58BF0192fFeBf); + address private constant HOODI_WETH_ADDRESS = 0x6CeA393234314e5c12d017F46a5cc9555c79fAee; + function setUp() public { - deployContractsHolesky(0); // on latest block + deployContractsHoodi(0); // on latest block } function test_create_puffer_module() public { @@ -41,20 +43,20 @@ contract PufferModuleManagerIntegrationTest is IntegrationTestHelper { function _depositToWETHEigenLayerStrategyAndDelegateTo(address restakingOperator) internal { // buy weth - vm.startPrank(0xA85Fdcb45aaFF3C310a47FE309D4a35FAfbdc0ad); - Weth(0x94373a4919B3240D86eA41593D5eBa789FEF3848).deposit{ value: 500 ether }(); - Weth(0x94373a4919B3240D86eA41593D5eBa789FEF3848).approve( - 0xdfB5f6CE42aAA7830E94ECFCcAd411beF4d4D5b6, type(uint256).max + vm.startPrank(0xA85Fdcb45aaFF3C310a47FE309D4a35FAfbdc0ad); // TODO Change + Weth(HOODI_WETH_ADDRESS).deposit{ value: 500 ether }(); + Weth(HOODI_WETH_ADDRESS).approve( + 0xeE45e76ddbEDdA2918b8C7E3035cd37Eab3b5D41, type(uint256).max ); // deposit into weth strategy - IStrategyManager(0xdfB5f6CE42aAA7830E94ECFCcAd411beF4d4D5b6).depositIntoStrategy( - IStrategy(0x80528D6e9A2BAbFc766965E0E26d5aB08D9CFaF9), - IERC20(0x94373a4919B3240D86eA41593D5eBa789FEF3848), + IStrategyManager(0xeE45e76ddbEDdA2918b8C7E3035cd37Eab3b5D41).depositIntoStrategy( + IStrategy(0x80528D6e9A2BAbFc766965E0E26d5aB08D9CFaF9), // TODO Change + IERC20(HOODI_WETH_ADDRESS), 500 ether ); ISignatureUtils.SignatureWithExpiry memory signatureWithExpiry; - IDelegationManager(0xA44151489861Fe9e3055d95adC98FbD462B948e7).delegateTo( + IDelegationManager(0x867837a9722C512e0862d8c2E15b8bE220E8b87d).delegateTo( // TODO Change restakingOperator, signatureWithExpiry, bytes32(0) ); } diff --git a/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol b/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol index 45ccae7c..e47523f5 100644 --- a/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol +++ b/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol @@ -19,19 +19,19 @@ import { RestakingOperatorController } from "../../src/RestakingOperatorControll contract PufferModuleManagerSlasherIntegrationTest is Test, DeployerHelper { PufferModuleManager public pufferModuleManager; - address PUFFER_MODULE_0_HOLESKY = 0x9017a172578458E1204691D6E1dB92ca61381655; - address EIGENPOD_0_HOLESKY = 0xeD9B08B8958B89E7A9008CAc0937E46F73Bf8f52; - address RESTAKING_OPERATOR_0_HOLESKY = 0x57b6FdEF3A23B81547df68F44e5524b987755c99; + address PUFFER_MODULE_0_HOODI = 0x1C898d25BC7B2819E8F0Af53A5a956F071f971fF; + address EIGENPOD_0_HOODI = 0xE7FDd7769f369cd1534Cb727A812Bce04553b24d; + address RESTAKING_OPERATOR_0_HOODI = 0x57b6FdEF3A23B81547df68F44e5524b987755c99; // TODO Change bytes32 PUFFER_MODULE_0_NAME = bytes32("PUFFER_MODULE_0"); DeployPufferModuleManager deployPufferModuleManager; DeployPufferModuleImplementation deployPufferModule; DeployRestakingOperator deployRestakingOperator; - uint32 START_BLOCK = 2994229; // Dec-23-2024 09:43:00 AM +UTC + uint32 START_BLOCK = 2994229; // Dec-23-2024 09:43:00 AM +UTC // TODO Change function setUp() public { - vm.createSelectFork(vm.rpcUrl("holesky"), START_BLOCK); + vm.createSelectFork(vm.rpcUrl("hoodi"), START_BLOCK); // I want to use the deployment scripts to deploy the contracts in tests. deployPufferModuleManager = new DeployPufferModuleManager(); @@ -74,9 +74,9 @@ contract PufferModuleManagerSlasherIntegrationTest is Test, DeployerHelper { IDelegationManagerTypes.Withdrawal[] memory withdrawals = new IDelegationManagerTypes.Withdrawal[](1); withdrawals[0] = IDelegationManagerTypes.Withdrawal({ - staker: PUFFER_MODULE_0_HOLESKY, - delegatedTo: RESTAKING_OPERATOR_0_HOLESKY, - withdrawer: PUFFER_MODULE_0_HOLESKY, + staker: PUFFER_MODULE_0_HOODI, + delegatedTo: RESTAKING_OPERATOR_0_HOODI, + withdrawer: PUFFER_MODULE_0_HOODI, nonce: 42, startBlock: START_BLOCK, strategies: strategies, @@ -89,7 +89,7 @@ contract PufferModuleManagerSlasherIntegrationTest is Test, DeployerHelper { bool[] memory receiveAsTokens = new bool[](1); receiveAsTokens[0] = true; - vm.roll(START_BLOCK + 50 + 1); // on Holesky its 50 blocks wait time, in Production it will be 14 days in blocks.. + vm.roll(START_BLOCK + 50 + 1); // on Hoodi its 50 blocks wait time, in Production it will be 14 days in blocks.. pufferModuleManager.callCompleteQueuedWithdrawals(PUFFER_MODULE_0_NAME, withdrawals, tokens, receiveAsTokens); } diff --git a/mainnet-contracts/test/fork-tests/ffi/PufferModuleManagerHoleskyFfi.t.sol b/mainnet-contracts/test/fork-tests/ffi/PufferModuleManagerHoleskyFfi.t.sol index a02f0fbb..db85c130 100644 --- a/mainnet-contracts/test/fork-tests/ffi/PufferModuleManagerHoleskyFfi.t.sol +++ b/mainnet-contracts/test/fork-tests/ffi/PufferModuleManagerHoleskyFfi.t.sol @@ -12,31 +12,31 @@ interface Weth { } // PufferTestnet V1 deployment -contract PufferModuleManagerHoleskyTestnetFFI is Test { +contract PufferModuleManagerHoodiTestnetFFI is Test { using BN254 for BN254.G1Point; using Strings for uint256; uint256[] privKeys; // https://github.com/Layr-Labs/eigenlayer-contracts?tab=readme-ov-file#deployments - address EIGEN_DA_REGISTRY_COORDINATOR_HOLESKY = 0x53012C69A189cfA2D9d29eb6F19B32e0A2EA3490; - address EIGEN_DA_SERVICE_MANAGER = 0xD4A7E1Bd8015057293f0D0A557088c286942e84b; + address EIGEN_DA_REGISTRY_COORDINATOR_HOODI = 0x53012C69A189cfA2D9d29eb6F19B32e0A2EA3490; // TODO Change + address EIGEN_DA_SERVICE_MANAGER = 0xD4A7E1Bd8015057293f0D0A557088c286942e84b; // TODO Change address BEACON_CHAIN_STRATEGY = 0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0; - address EIGEN_POD_MANAGER = 0x30770d7E3e71112d7A6b7259542D1f680a70e315; - address DELAYED_WITHDRAWAL_ROUTER = 0x642c646053eaf2254f088e9019ACD73d9AE0FA32; - address DELEGATION_MANAGER = 0xA44151489861Fe9e3055d95adC98FbD462B948e7; + address EIGEN_POD_MANAGER = 0xcd1442415Fc5C29Aa848A49d2e232720BE07976c; + address DELAYED_WITHDRAWAL_ROUTER = 0x642c646053eaf2254f088e9019ACD73d9AE0FA32; // TODO Change + address DELEGATION_MANAGER = 0x867837a9722C512e0862d8c2E15b8bE220E8b87d; - // Puffer Holesky deployment + // Puffer Hoodi deployment address PUFFER_SHARED_DEV_WALLET = 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; - address ACCESS_MANAGER_HOLESKY = 0xA6c916f85DAfeb6f726E03a1Ce8d08cf835138fF; - address MODULE_BEACON_HOLESKY = 0x5B81A4579f466fB17af4d8CC0ED51256b94c61D4; - address PUFFER_PROTOCOL_HOLESKY = 0x705E27D6A6A0c77081D32C07DbDE5A1E139D3F14; - address PUFFER_MODULE_MANAGER = 0xe4695ab93163F91665Ce5b96527408336f070a71; - address PUFFER_MODULE_0_HOLESKY = 0x0B0456ec773B7D89C9deCc38b682F98556CF9862; - // https://holesky.eigenlayer.xyz/operator/0xe2c2dc296a0bff351f6bc3e98d37ea798e393e56 - address RESTAKING_OPERATOR_CONTRACT = 0xe2c2dc296a0bFF351F6bC3e98D37ea798e393e56; - address RESTAKING_OPERATOR_BEACON = 0xa7DC88c059F57ADcE41070cEfEFd31F74649a261; - address REWARDS_COORDINATOR = 0xAcc1fb458a1317E886dB376Fc8141540537E68fE; + address ACCESS_MANAGER_HOODI = 0x9a86395B4c5B03a3D727A9037a122470adfA6F0e; + address MODULE_BEACON_HOODI = 0x6F2BDD64A7ba1Ca06784f58D2dBaF3f54a010F49; + address PUFFER_PROTOCOL_HOODI = 0x7dE52e679e82395CB62C5B574A81cef637529fba; + address PUFFER_MODULE_MANAGER = 0x4a143618836f8bb84B328654f75d6C130500e375; + address PUFFER_MODULE_0_HOODI = 0x1C898d25BC7B2819E8F0Af53A5a956F071f971fF; + // https://hoodi.eigenlayer.xyz/operator/0xe2c2dc296a0bff351f6bc3e98d37ea798e393e56 // TODO Change + address RESTAKING_OPERATOR_CONTRACT = 0xe2c2dc296a0bFF351F6bC3e98D37ea798e393e56; // TODO Change + address RESTAKING_OPERATOR_BEACON = 0x9f9aa46c3b98aDDc1eEef87De25f986024f7C6Bb; + address REWARDS_COORDINATOR = 0x29e8572678e0c272350aa0b4B8f304E47EBcd5e7; function _mulGo(uint256 x) internal returns (BN254.G2Point memory g2Point) { string[] memory inputs = new string[](3); diff --git a/mainnet-contracts/test/helpers/IntegrationTestHelper.sol b/mainnet-contracts/test/helpers/IntegrationTestHelper.sol index 6ce53cbf..6d3b65db 100644 --- a/mainnet-contracts/test/helpers/IntegrationTestHelper.sol +++ b/mainnet-contracts/test/helpers/IntegrationTestHelper.sol @@ -13,7 +13,7 @@ import { IEnclaveVerifier } from "../../src/interface/IEnclaveVerifier.sol"; import { AccessManager } from "@openzeppelin/contracts/access/manager/AccessManager.sol"; contract IntegrationTestHelper is Test { - address DAO = 0xC4a2E012024d4ff28a4E2334F58D4Cc233EB1FE1; + address DAO = 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; PufferProtocol public pufferProtocol; UpgradeableBeacon public beacon; PufferModuleManager public moduleManager; @@ -27,12 +27,12 @@ contract IntegrationTestHelper is Test { address PAYMASTER = 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; // custom block number - function deployContractsHolesky(uint256 blockNumber) public virtual { + function deployContractsHoodi(uint256 blockNumber) public virtual { // see foundry.toml for the rpc urls if (blockNumber == 0) { - vm.createSelectFork(vm.rpcUrl("holesky")); + vm.createSelectFork(vm.rpcUrl("hoodi")); } else { - vm.createSelectFork(vm.rpcUrl("holesky"), blockNumber); + vm.createSelectFork(vm.rpcUrl("hoodi"), blockNumber); } address[] memory guardians = new address[](1); @@ -42,8 +42,8 @@ contract IntegrationTestHelper is Test { } // 'default' block number - function deployContractsHolesky() public virtual { - deployContractsHolesky(1_212_252); + function deployContractsHoodi() public virtual { + deployContractsHoodi(1_212_252); // TODO Change } function _deployAndLabel(address[] memory guardians, uint256 threshold) internal { From 04f6cfb0a8c4ee2c3b332a844a6a2cdb9b5d2d02 Mon Sep 17 00:00:00 2001 From: eladiosch <3090613+eladiosch@users.noreply.github.com> Date: Tue, 20 Jan 2026 10:30:35 +0000 Subject: [PATCH 07/51] forge fmt --- mainnet-contracts/script/DeployerHelper.s.sol | 100 ++++++++++++------ .../PufferModuleManager.integration.t.sol | 7 +- 2 files changed, 68 insertions(+), 39 deletions(-) diff --git a/mainnet-contracts/script/DeployerHelper.s.sol b/mainnet-contracts/script/DeployerHelper.s.sol index 9c79f809..e0307464 100644 --- a/mainnet-contracts/script/DeployerHelper.s.sol +++ b/mainnet-contracts/script/DeployerHelper.s.sol @@ -31,7 +31,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0xb7d83623906AC3fa577F45B7D2b9D4BD26BC5d76 return 0xb7d83623906AC3fa577F45B7D2b9D4BD26BC5d76; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0 return 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; } else if (block.chainid == hoodi) { @@ -80,7 +81,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x282A69142bac47855C3fbE1693FcC4bA3B4d5Ed6 return 0x282A69142bac47855C3fbE1693FcC4bA3B4d5Ed6; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0x82a44a6489936FFF841eecAF650Aa4D9708E4312 return 0x82a44a6489936FFF841eecAF650Aa4D9708E4312; } @@ -101,7 +103,8 @@ abstract contract DeployerHelper is Script { vm.label(implementation, contractName); console.log("Deployed", contractName, "at", implementation); - if (block.chainid == holesky) { // @DEPRECATED + if (block.chainid == holesky) { + // @DEPRECATED AccessManager(_getAccessManager()).execute( proxyTarget, abi.encodeCall(UUPSUpgradeable.upgradeToAndCall, (address(implementation), data)) ); @@ -126,7 +129,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x946Ae7b21de3B0793Bb469e263517481B74A6950 return 0x946Ae7b21de3B0793Bb469e263517481B74A6950; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0x61A44645326846F9b5d9c6f91AD27C3aD28EA390 return 0x61A44645326846F9b5d9c6f91AD27C3aD28EA390; } else if (block.chainid == hoodi) { @@ -141,7 +145,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0xD92145c07f8Ed1D392c1B88017934E301CC1c3Cd return 0xD92145c07f8Ed1D392c1B88017934E301CC1c3Cd; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0xcAe751b75833ef09627549868A04E32679386e7C return 0xcAe751b75833ef09627549868A04E32679386e7C; } else if (block.chainid == hoodi) { @@ -157,7 +162,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x6756B856Dd3843C84249a6A31850cB56dB824c4B return 0x6756B856Dd3843C84249a6A31850cB56dB824c4B; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0x99c3E46E575df251149866285DdA7DAEba875B71 return 0x99c3E46E575df251149866285DdA7DAEba875B71; } else if (block.chainid == hoodi) { @@ -172,7 +178,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x00000000219ab540356cBB839Cbe05303d7705Fa return 0x00000000219ab540356cBB839Cbe05303d7705Fa; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0x4242424242424242424242424242424242424242 return 0x4242424242424242424242424242424242424242; } else if (block.chainid == hoodi) { @@ -187,7 +194,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x628b183F248a142A598AA2dcCCD6f7E480a7CcF2 return 0x628b183F248a142A598AA2dcCCD6f7E480a7CcF2; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0x0910310130d1c062DEF8B807528bdac80203BC66 return 0x0910310130d1c062DEF8B807528bdac80203BC66; } else if (block.chainid == hoodi) { @@ -202,7 +210,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0xdd38A5a7789C74fc7F64556fc772343658EEBb04 return 0xdd38A5a7789C74fc7F64556fc772343658EEBb04; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0x4B0542470935ed4b085C3AD1983E85f5623ABf89 return 0x4B0542470935ed4b085C3AD1983E85f5623ABf89; } else if (block.chainid == hoodi) { @@ -217,7 +226,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x91E677b07F7AF907ec9a428aafA9fc14a0d3A338 return 0x91E677b07F7AF907ec9a428aafA9fc14a0d3A338; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0x30770d7E3e71112d7A6b7259542D1f680a70e315 return 0x30770d7E3e71112d7A6b7259542D1f680a70e315; } else if (block.chainid == hoodi) { @@ -232,7 +242,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A return 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0xA44151489861Fe9e3055d95adC98FbD462B948e7 return 0xA44151489861Fe9e3055d95adC98FbD462B948e7; } else if (block.chainid == hoodi) { @@ -247,7 +258,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x1565E55B63675c703fcC3778BD33eA97F7bE882F return 0x1565E55B63675c703fcC3778BD33eA97F7bE882F; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0x09BE86B01c1e32dCa2ebdEDb01cD5A3F798b80C5 return 0x09BE86B01c1e32dCa2ebdEDb01cD5A3F798b80C5; } else if (block.chainid == hoodi) { @@ -262,7 +274,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // Mainnet Timelock: https://etherscan.io/address/0x3C28B7c7Ba1A1f55c9Ce66b263B33B204f2126eA return 0x3C28B7c7Ba1A1f55c9Ce66b263B33B204f2126eA; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // Holesky Timelock: https://explorer.pops.one/address/0x829aF0B3d099a12F0aE1b806f466EF771E2C07F8 return 0x829aF0B3d099a12F0aE1b806f466EF771E2C07F8; } else if (block.chainid == hoodi) { @@ -277,7 +290,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x7750d328b314EfFa365A0402CcfD489B80B0adda return 0x7750d328b314EfFa365A0402CcfD489B80B0adda; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0xAcc1fb458a1317E886dB376Fc8141540537E68fE return 0xAcc1fb458a1317E886dB376Fc8141540537E68fE; } else if (block.chainid == hoodi) { @@ -292,7 +306,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84 return 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0x3F1c547b21f65e10480dE3ad8E19fAAC46C95034 return 0x3F1c547b21f65e10480dE3ad8E19fAAC46C95034; } else if (block.chainid == hoodi) { @@ -307,8 +322,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { return 0x8d09a4502Cc8Cf1547aD300E066060D043f6982D; } - if(block.chainid == hoodi) { - return 0x7E99eE3C66636DE415D2d7C880938F2f40f94De4; + if (block.chainid == hoodi) { + return 0x7E99eE3C66636DE415D2d7C880938F2f40f94De4; } revert("WstETH not available for this chain"); @@ -318,7 +333,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x93c4b944D05dfe6df7645A86cd2206016c51564D return 0x93c4b944D05dfe6df7645A86cd2206016c51564D; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0x7D704507b76571a51d9caE8AdDAbBFd0ba0e63d3 return 0x7D704507b76571a51d9caE8AdDAbBFd0ba0e63d3; } else if (block.chainid == hoodi) { @@ -333,7 +349,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x858646372CC42E1A627fcE94aa7A7033e7CF075A return 0x858646372CC42E1A627fcE94aa7A7033e7CF075A; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0xdfB5f6CE42aAA7830E94ECFCcAd411beF4d4D5b6 return 0xdfB5f6CE42aAA7830E94ECFCcAd411beF4d4D5b6; } else if (block.chainid == hoodi) { @@ -348,7 +365,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x0BE2aE0edbeBb517541DF217EF0074FC9a9e994f return 0x0BE2aE0edbeBb517541DF217EF0074FC9a9e994f; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0x8e043ed3F06720615685D4978770Cd5C8fe90fe3 return 0x8e043ed3F06720615685D4978770Cd5C8fe90fe3; } else if (block.chainid == hoodi) { @@ -363,7 +381,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A return 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0xA44151489861Fe9e3055d95adC98FbD462B948e7 return 0xA44151489861Fe9e3055d95adC98FbD462B948e7; } else if (block.chainid == hoodi) { @@ -378,7 +397,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 return 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0x1d181cBd1825e9eBC6AD966878D555A7215FF4F0 return 0x1d181cBd1825e9eBC6AD966878D555A7215FF4F0; } else if (block.chainid == hoodi) { @@ -393,7 +413,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x889edC2eDab5f40e902b864aD4d7AdE8E412F9B1 return 0x889edC2eDab5f40e902b864aD4d7AdE8E412F9B1; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0xc7cc160b58F8Bb0baC94b80847E2CF2800565C50 return 0xc7cc160b58F8Bb0baC94b80847E2CF2800565C50; } else if (block.chainid == hoodi) { @@ -411,7 +432,8 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == mainnet) { // https://etherscan.io/address/0x8c1686069474410E6243425f4a10177a94EBEE11 return 0x8c1686069474410E6243425f4a10177a94EBEE11; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0x180a345906e42293dcAd5CCD9b0e1DB26aE0274e return 0x180a345906e42293dcAd5CCD9b0e1DB26aE0274e; } else if (block.chainid == hoodi) { @@ -435,7 +457,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0xD9A442856C234a39a81a089C06451EBAa4306a72 return 0xD9A442856C234a39a81a089C06451EBAa4306a72; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0x9196830bB4c05504E0A8475A0aD566AceEB6BeC9 return 0x9196830bB4c05504E0A8475A0aD566AceEB6BeC9; } else if (block.chainid == sepolia) { @@ -454,7 +477,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x9E1E4fCb49931df5743e659ad910d331735C3860 return 0x9E1E4fCb49931df5743e659ad910d331735C3860; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0x20377c306451140119C9967Ba6D0158a05b4eD07 return 0x20377c306451140119C9967Ba6D0158a05b4eD07; } else if (block.chainid == hoodi) { @@ -469,7 +493,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x7D26AD6F6BA9D6bA1de0218Ae5e20CD3a273a55A return 0x7D26AD6F6BA9D6bA1de0218Ae5e20CD3a273a55A; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0xB028194785178a94Fe608994A4d5AD84c285A640 return 0xB028194785178a94Fe608994A4d5AD84c285A640; } else if (block.chainid == hoodi) { @@ -484,7 +509,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0xf7b6B32492c2e13799D921E84202450131bd238B return 0xf7b6B32492c2e13799D921E84202450131bd238B; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0xE00c79408B9De5BaD2FDEbB1688997a68eC988CD return 0xE00c79408B9De5BaD2FDEbB1688997a68eC988CD; } else if (block.chainid == hoodi) { @@ -499,7 +525,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x953b4113716CE71596F7Ba6B0E75050c25c493c1 return 0x953b4113716CE71596F7Ba6B0E75050c25c493c1; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/- return address(0); } else if (block.chainid == hoodi) { @@ -571,7 +598,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0xa4931a9F9Aaf79057334371D6f62164743f97b18 return 0xa4931a9F9Aaf79057334371D6f62164743f97b18; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0xfe235A03d87FCBf94E91536955c8a6b1FF50A5C0 return 0xfe235A03d87FCBf94E91536955c8a6b1FF50A5C0; } else if (block.chainid == hoodi) { @@ -603,7 +631,8 @@ abstract contract DeployerHelper is Script { } else if (block.chainid == base) { // https://basescan.org/address/0x1a44076050125825900e736c501f859c50fE728c return 0x1a44076050125825900e736c501f859c50fE728c; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0x6EDCE65403992e310A62460808c4b910D972f10f return 0x6EDCE65403992e310A62460808c4b910D972f10f; } else if (block.chainid == sepolia) { @@ -615,7 +644,8 @@ abstract contract DeployerHelper is Script { } function _getLayerZeroDestinationEID() internal view returns (uint32) { - if (block.chainid == holesky) { // @DEPRECATED + if (block.chainid == holesky) { + // @DEPRECATED // https://docs.layerzero.network/v2/deployments/deployed-contracts return 40217; } else if (block.chainid == sepolia) { @@ -629,7 +659,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x65d2dd7A66a2733a36559fE900A236280A05FBD6 return 0x65d2dd7A66a2733a36559fE900A236280A05FBD6; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0 return 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; } else if (block.chainid == hoodi) { @@ -668,7 +699,8 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0xC0896ab1A8cae8c2C1d27d011eb955Cca955580d return 0xC0896ab1A8cae8c2C1d27d011eb955Cca955580d; - } else if (block.chainid == holesky) { // @DEPRECATED + } else if (block.chainid == holesky) { + // @DEPRECATED // https://holesky.etherscan.io/address/0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0 return 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; } else if (block.chainid == hoodi) { diff --git a/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol b/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol index 8a53f474..2add53fc 100644 --- a/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol +++ b/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol @@ -45,9 +45,7 @@ contract PufferModuleManagerIntegrationTest is IntegrationTestHelper { // buy weth vm.startPrank(0xA85Fdcb45aaFF3C310a47FE309D4a35FAfbdc0ad); // TODO Change Weth(HOODI_WETH_ADDRESS).deposit{ value: 500 ether }(); - Weth(HOODI_WETH_ADDRESS).approve( - 0xeE45e76ddbEDdA2918b8C7E3035cd37Eab3b5D41, type(uint256).max - ); + Weth(HOODI_WETH_ADDRESS).approve(0xeE45e76ddbEDdA2918b8C7E3035cd37Eab3b5D41, type(uint256).max); // deposit into weth strategy IStrategyManager(0xeE45e76ddbEDdA2918b8C7E3035cd37Eab3b5D41).depositIntoStrategy( IStrategy(0x80528D6e9A2BAbFc766965E0E26d5aB08D9CFaF9), // TODO Change @@ -57,8 +55,7 @@ contract PufferModuleManagerIntegrationTest is IntegrationTestHelper { ISignatureUtils.SignatureWithExpiry memory signatureWithExpiry; IDelegationManager(0x867837a9722C512e0862d8c2E15b8bE220E8b87d).delegateTo( // TODO Change - restakingOperator, signatureWithExpiry, bytes32(0) - ); + restakingOperator, signatureWithExpiry, bytes32(0)); } // Creates a new restaking operator and returns it From f44121f5071aae6cec46a9b02e78c559e7e221d1 Mon Sep 17 00:00:00 2001 From: Eladio Date: Wed, 21 Jan 2026 16:57:34 +0100 Subject: [PATCH 08/51] Updated names and addresses --- mainnet-contracts/script/DeployerHelper.s.sol | 13 ++++++------- ...yFfi.t.sol => PufferModuleManagerHoodiFfi.t.sol} | 0 2 files changed, 6 insertions(+), 7 deletions(-) rename mainnet-contracts/test/fork-tests/ffi/{PufferModuleManagerHoleskyFfi.t.sol => PufferModuleManagerHoodiFfi.t.sol} (100%) diff --git a/mainnet-contracts/script/DeployerHelper.s.sol b/mainnet-contracts/script/DeployerHelper.s.sol index e0307464..dc818d02 100644 --- a/mainnet-contracts/script/DeployerHelper.s.sol +++ b/mainnet-contracts/script/DeployerHelper.s.sol @@ -141,21 +141,20 @@ abstract contract DeployerHelper is Script { revert("Treasury not available for this chain"); } - function _getEigenSlasher() internal view returns (address) { + function _getAllocationManager() internal view returns (address) { if (block.chainid == mainnet) { - // https://etherscan.io/address/0xD92145c07f8Ed1D392c1B88017934E301CC1c3Cd - return 0xD92145c07f8Ed1D392c1B88017934E301CC1c3Cd; + // https://etherscan.io/address/0x948a420b8CC1d6BFd0B6087C2E7c344a2CD0bc39 + return 0x948a420b8CC1d6BFd0B6087C2E7c344a2CD0bc39; } else if (block.chainid == holesky) { // @DEPRECATED // https://holesky.etherscan.io/address/0xcAe751b75833ef09627549868A04E32679386e7C return 0xcAe751b75833ef09627549868A04E32679386e7C; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? - //return ???; - // TODO Find the address + // https://hoodi.etherscan.io/address/0x95a7431400F362F3647a69535C5666cA0133CAA0 + return 0x95a7431400F362F3647a69535C5666cA0133CAA0; } - revert("EigenSlasher not available for this chain"); + revert("AllocationManager not available for this chain"); } function _getRestakingOperatorBeacon() internal view returns (address) { diff --git a/mainnet-contracts/test/fork-tests/ffi/PufferModuleManagerHoleskyFfi.t.sol b/mainnet-contracts/test/fork-tests/ffi/PufferModuleManagerHoodiFfi.t.sol similarity index 100% rename from mainnet-contracts/test/fork-tests/ffi/PufferModuleManagerHoleskyFfi.t.sol rename to mainnet-contracts/test/fork-tests/ffi/PufferModuleManagerHoodiFfi.t.sol From 2ec2cd99f11ebd3dcab4dd7227481dcc3998f113 Mon Sep 17 00:00:00 2001 From: Eladio Date: Wed, 21 Jan 2026 18:27:30 +0100 Subject: [PATCH 09/51] Fixed wrong function name and added eigen addresses --- mainnet-contracts/script/DeployRestakingOperator.s.sol | 6 +++--- .../test/fork-tests/PufferModuleManager.integration.t.sol | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mainnet-contracts/script/DeployRestakingOperator.s.sol b/mainnet-contracts/script/DeployRestakingOperator.s.sol index e0241320..87b84d99 100644 --- a/mainnet-contracts/script/DeployRestakingOperator.s.sol +++ b/mainnet-contracts/script/DeployRestakingOperator.s.sol @@ -24,7 +24,7 @@ contract DeployRestakingOperator is DeployerHelper { RestakingOperator restakingOperatorImplementation = new RestakingOperator({ delegationManager: IDelegationManager(_getEigenDelegationManager()), - allocationManager: IAllocationManager(_getEigenSlasher()), + allocationManager: IAllocationManager(_getAllocationManager()), moduleManager: PufferModuleManager(payable(_getPufferModuleManager())), rewardsCoordinator: IRewardsCoordinator(_getRewardsCoordinator()), restakingOperatorController: _getRestakingOperatorController() @@ -49,7 +49,7 @@ contract DeployRestakingOperator is DeployerHelper { RestakingOperator restakingOperatorImplementation = new RestakingOperator({ delegationManager: IDelegationManager(_getEigenDelegationManager()), - allocationManager: IAllocationManager(_getEigenSlasher()), + allocationManager: IAllocationManager(_getAllocationManager()), moduleManager: PufferModuleManager(payable(_getPufferModuleManager())), rewardsCoordinator: IRewardsCoordinator(_getRewardsCoordinator()), restakingOperatorController: _getRestakingOperatorController() @@ -69,7 +69,7 @@ contract DeployRestakingOperator is DeployerHelper { RestakingOperator restakingOperatorImplementation = new RestakingOperator({ delegationManager: IDelegationManager(_getEigenDelegationManager()), - allocationManager: IAllocationManager(_getEigenSlasher()), + allocationManager: IAllocationManager(_getAllocationManager()), moduleManager: PufferModuleManager(payable(_getPufferModuleManager())), rewardsCoordinator: IRewardsCoordinator(_getRewardsCoordinator()), restakingOperatorController: restakingOperatorController diff --git a/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol b/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol index 2add53fc..65a5c534 100644 --- a/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol +++ b/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol @@ -26,8 +26,8 @@ contract PufferModuleManagerIntegrationTest is IntegrationTestHelper { uint256[] privKeys; - address EIGEN_DA_REGISTRY_COORDINATOR_HOODI = 0x53012C69A189cfA2D9d29eb6F19B32e0A2EA3490; // TODO Change - address EIGEN_DA_SERVICE_MANAGER = 0xD4A7E1Bd8015057293f0D0A557088c286942e84b; // TODO Change + address EIGEN_DA_REGISTRY_COORDINATOR_HOODI = 0xB5b76D561eeF36CD772890C94C6Bde8b895455e2; + address EIGEN_DA_SERVICE_MANAGER = 0x3FF2204A567C15dC3731140B95362ABb4b17d8ED; // IAVSDirectory public avsDirectory = IAVSDirectory(0x055733000064333CaDDbC92763c58BF0192fFeBf); address private constant HOODI_WETH_ADDRESS = 0x6CeA393234314e5c12d017F46a5cc9555c79fAee; @@ -48,13 +48,13 @@ contract PufferModuleManagerIntegrationTest is IntegrationTestHelper { Weth(HOODI_WETH_ADDRESS).approve(0xeE45e76ddbEDdA2918b8C7E3035cd37Eab3b5D41, type(uint256).max); // deposit into weth strategy IStrategyManager(0xeE45e76ddbEDdA2918b8C7E3035cd37Eab3b5D41).depositIntoStrategy( - IStrategy(0x80528D6e9A2BAbFc766965E0E26d5aB08D9CFaF9), // TODO Change + IStrategy(0x24579aD4fe83aC53546E5c2D3dF5F85D6383420d), IERC20(HOODI_WETH_ADDRESS), 500 ether ); ISignatureUtils.SignatureWithExpiry memory signatureWithExpiry; - IDelegationManager(0x867837a9722C512e0862d8c2E15b8bE220E8b87d).delegateTo( // TODO Change + IDelegationManager(0x867837a9722C512e0862d8c2E15b8bE220E8b87d).delegateTo( restakingOperator, signatureWithExpiry, bytes32(0)); } From 46c378123d12240953c6b48aeb2a3e234384ac73 Mon Sep 17 00:00:00 2001 From: eladiosch <3090613+eladiosch@users.noreply.github.com> Date: Wed, 21 Jan 2026 17:31:20 +0000 Subject: [PATCH 10/51] forge fmt --- .../test/fork-tests/PufferModuleManager.integration.t.sol | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol b/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol index 65a5c534..1a3992ae 100644 --- a/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol +++ b/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol @@ -48,14 +48,13 @@ contract PufferModuleManagerIntegrationTest is IntegrationTestHelper { Weth(HOODI_WETH_ADDRESS).approve(0xeE45e76ddbEDdA2918b8C7E3035cd37Eab3b5D41, type(uint256).max); // deposit into weth strategy IStrategyManager(0xeE45e76ddbEDdA2918b8C7E3035cd37Eab3b5D41).depositIntoStrategy( - IStrategy(0x24579aD4fe83aC53546E5c2D3dF5F85D6383420d), - IERC20(HOODI_WETH_ADDRESS), - 500 ether + IStrategy(0x24579aD4fe83aC53546E5c2D3dF5F85D6383420d), IERC20(HOODI_WETH_ADDRESS), 500 ether ); ISignatureUtils.SignatureWithExpiry memory signatureWithExpiry; IDelegationManager(0x867837a9722C512e0862d8c2E15b8bE220E8b87d).delegateTo( - restakingOperator, signatureWithExpiry, bytes32(0)); + restakingOperator, signatureWithExpiry, bytes32(0) + ); } // Creates a new restaking operator and returns it From 38acf333203349b765cc463870caf6bcd32e2300 Mon Sep 17 00:00:00 2001 From: Eladio Date: Wed, 28 Jan 2026 11:48:34 +0100 Subject: [PATCH 11/51] Remove stale interfaces submodule and add automata-dcap-attestation --- .gitmodules | 3 +++ mainnet-contracts/lib/.gitkeep | 0 mainnet-contracts/lib/automata-dcap-attestation | 1 + mainnet-contracts/lib/interfaces | 1 - 4 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 mainnet-contracts/lib/.gitkeep create mode 160000 mainnet-contracts/lib/automata-dcap-attestation delete mode 160000 mainnet-contracts/lib/interfaces diff --git a/.gitmodules b/.gitmodules index 73206927..a311b11b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "partners/layerzero/lib/forge-std"] path = partners/layerzero/lib/forge-std url = https://github.com/foundry-rs/forge-std +[submodule "mainnet-contracts/lib/automata-dcap-attestation"] + path = mainnet-contracts/lib/automata-dcap-attestation + url = https://github.com/automata-network/automata-dcap-attestation diff --git a/mainnet-contracts/lib/.gitkeep b/mainnet-contracts/lib/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/mainnet-contracts/lib/automata-dcap-attestation b/mainnet-contracts/lib/automata-dcap-attestation new file mode 160000 index 00000000..9c963126 --- /dev/null +++ b/mainnet-contracts/lib/automata-dcap-attestation @@ -0,0 +1 @@ +Subproject commit 9c96312657f2a905003f6ebf565d5742422f24a2 diff --git a/mainnet-contracts/lib/interfaces b/mainnet-contracts/lib/interfaces deleted file mode 160000 index 2e028738..00000000 --- a/mainnet-contracts/lib/interfaces +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2e0287382f95ce64abd7f5257e0a17a84795f370 From 466fada1e920062f05770b0680f1f4cec393c2d1 Mon Sep 17 00:00:00 2001 From: Eladio Date: Wed, 28 Jan 2026 18:29:37 +0100 Subject: [PATCH 12/51] Installed dependencies and implemented changes in GuardianModule --- .gitmodules | 6 +- mainnet-contracts/foundry.lock | 17 +++ mainnet-contracts/lib/.gitkeep | 0 .../lib/automata-dcap-attestation | 1 - mainnet-contracts/remappings.txt | 3 +- mainnet-contracts/src/GuardianModule.sol | 108 ++++++++---------- .../src/interface/IGuardianModule.sol | 75 +++++++----- .../src/struct/GuardianModuleStructs.sol | 35 ++++++ 8 files changed, 151 insertions(+), 94 deletions(-) create mode 100644 mainnet-contracts/foundry.lock delete mode 100644 mainnet-contracts/lib/.gitkeep delete mode 160000 mainnet-contracts/lib/automata-dcap-attestation create mode 100644 mainnet-contracts/src/struct/GuardianModuleStructs.sol diff --git a/.gitmodules b/.gitmodules index a311b11b..a04c15e3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,6 +4,6 @@ [submodule "partners/layerzero/lib/forge-std"] path = partners/layerzero/lib/forge-std url = https://github.com/foundry-rs/forge-std -[submodule "mainnet-contracts/lib/automata-dcap-attestation"] - path = mainnet-contracts/lib/automata-dcap-attestation - url = https://github.com/automata-network/automata-dcap-attestation +[submodule "mainnet-contracts/lib/automata-tee-workload-measurement"] + path = mainnet-contracts/lib/automata-tee-workload-measurement + url = https://github.com/automata-network/automata-tee-workload-measurement diff --git a/mainnet-contracts/foundry.lock b/mainnet-contracts/foundry.lock new file mode 100644 index 00000000..cae4ef6e --- /dev/null +++ b/mainnet-contracts/foundry.lock @@ -0,0 +1,17 @@ +{ + "../partners/chainlink/lib/forge-std": { + "rev": "3b20d60d14b343ee4f908cb8079495c07f5e8981" + }, + "lib/automata-dcap-attestation": { + "tag": { + "name": "v1.1.0", + "rev": "9c96312657f2a905003f6ebf565d5742422f24a2" + } + }, + "lib/automata-tpm-attestation": { + "rev": "1a3ab2bc4886ac5313365f94e3d60dcf01fd9c41" + }, + "partners/chainlink/lib/forge-std": { + "rev": "3b20d60d14b343ee4f908cb8079495c07f5e8981" + } +} \ No newline at end of file diff --git a/mainnet-contracts/lib/.gitkeep b/mainnet-contracts/lib/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/mainnet-contracts/lib/automata-dcap-attestation b/mainnet-contracts/lib/automata-dcap-attestation deleted file mode 160000 index 9c963126..00000000 --- a/mainnet-contracts/lib/automata-dcap-attestation +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9c96312657f2a905003f6ebf565d5742422f24a2 diff --git a/mainnet-contracts/remappings.txt b/mainnet-contracts/remappings.txt index 4be7f8e9..849502fb 100644 --- a/mainnet-contracts/remappings.txt +++ b/mainnet-contracts/remappings.txt @@ -18,4 +18,5 @@ solidity-stringutils/=node_modules/solidity-stringutils @layerzerolabs/lz-evm-messagelib-v2/=node_modules/@layerzerolabs/lz-evm-messagelib-v2/ @layerzerolabs/lz-evm-v1-0.7/=node_modules/@layerzerolabs/lz-evm-v1-0.7/ @layerzerolabs/test-devtools-evm-foundry/=node_modules/@layerzerolabs/test-devtools-evm-foundry/ -solidity-bytes-utils/=node_modules/solidity-bytes-utils/ \ No newline at end of file +solidity-bytes-utils/=node_modules/solidity-bytes-utils/ +@automata-network/automata-tee-workload-measurement=lib/automata-tee-workload-measurement/src/ \ No newline at end of file diff --git a/mainnet-contracts/src/GuardianModule.sol b/mainnet-contracts/src/GuardianModule.sol index fec650c9..abb1297c 100644 --- a/mainnet-contracts/src/GuardianModule.sol +++ b/mainnet-contracts/src/GuardianModule.sol @@ -12,6 +12,8 @@ import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableS import { LibGuardianMessages } from "./LibGuardianMessages.sol"; import { Address } from "@openzeppelin/contracts/utils/Address.sol"; import { StoppedValidatorInfo } from "./struct/StoppedValidatorInfo.sol"; +import { IWorkloadVerifier } from "@automata-network/automata-tee-workload-measurement/interfaces/IWorkloadVerifier.sol"; +import { TdxRegistrationData, GoldenMeasurementInfo, GuardianData } from "./struct/GuardianModuleStructs.sol"; /** * @title Guardian module @@ -37,9 +39,9 @@ contract GuardianModule is AccessManaged, IGuardianModule { uint256 internal constant _EJECTION_THRESHOLD_BALANCE = 31.75 ether; /** - * @notice Enclave Verifier smart contract + * @notice Workload Verifier smart contract */ - IEnclaveVerifier public immutable ENCLAVE_VERIFIER; + IWorkloadVerifier public immutable WORKLOAD_VERIFIER; /** * @dev Guardians set @@ -51,36 +53,23 @@ contract GuardianModule is AccessManaged, IGuardianModule { */ uint256 internal _threshold; - /** - * @dev MRSIGNER value for SGX - */ - bytes32 internal _mrsigner; - - /** - * @dev MRENCLAVE value for SGX - */ - bytes32 internal _mrenclave; - /** * @dev This variable is for the Guardian's to coordinate on when to eject Puffer validators */ uint256 internal _ejectionThreshold; /** - * @dev Enclave data - * The guardian doesn't know the Secret Key of an enclave wallet + * @dev Mapping of a Guardian's EOA to enclave data */ - struct GuardianData { - bytes enclavePubKey; - address enclaveAddress; - } + mapping(address guardian => GuardianData data) internal _guardianEnclaves; /** - * @dev Mapping of a Guardian's EOA to enclave data + * @dev Mapping of Golden Measurement registry hash to GoldenMeasurementInfo */ - mapping(address guardian => GuardianData data) internal _guardianEnclaves; + mapping(bytes32 hash => GoldenMeasurementInfo info) internal _goldenMeasurements; + - constructor(IEnclaveVerifier verifier, address[] memory guardians, uint256 threshold, address pufferAuthority) + constructor(IWorkloadVerifier verifier, address[] memory guardians, uint256 threshold, address pufferAuthority) payable AccessManaged(pufferAuthority) { @@ -90,7 +79,7 @@ contract GuardianModule is AccessManaged, IGuardianModule { if (address(pufferAuthority) == address(0)) { revert InvalidAddress(); } - ENCLAVE_VERIFIER = verifier; + WORKLOAD_VERIFIER = verifier; for (uint256 i = 0; i < guardians.length; ++i) { _addGuardian(guardians[i]); } @@ -241,11 +230,20 @@ contract GuardianModule is AccessManaged, IGuardianModule { * @inheritdoc IGuardianModule * @dev Restricted to the DAO */ - function setGuardianEnclaveMeasurements(bytes32 newMrEnclave, bytes32 newMrSigner) external restricted { - emit MrEnclaveChanged(_mrenclave, newMrEnclave); - emit MrSignerChanged(_mrsigner, newMrSigner); - _mrenclave = newMrEnclave; - _mrsigner = newMrSigner; + function registerGoldenMeasurement(bytes32 hash, GoldenMeasurementInfo calldata info) external restricted { + require(hash != bytes32(0), InvalidData()); + _goldenMeasurements[hash] = info; + emit GoldenMeasurementRegistered(hash, info); + } + + + /** + * @inheritdoc IGuardianModule + * @dev Restricted to the DAO + */ + function deregisterGoldenMeasurement(bytes32 hash) external restricted { + delete _goldenMeasurements[hash]; + emit GoldenMeasurementDeregistered(hash); } /** @@ -296,33 +294,28 @@ contract GuardianModule is AccessManaged, IGuardianModule { return _guardians.values(); } - /** - * @inheritdoc IGuardianModule - */ - function rotateGuardianKey(uint256 blockNumber, bytes calldata pubKey, RaveEvidence calldata evidence) external { - address guardian = msg.sender; - - if (!_guardians.contains(guardian)) { - revert Unauthorized(); - } + function rotateGuardianKey( + uint256 blockNumber, + bytes calldata pubKey, + TdxRegistrationData calldata data // TDX DCAP + ) external payable { + (, bytes32 measurementHash, bytes memory tpmExtraData) = + WORKLOAD_VERIFIER.verifyAttestationAndGetMeasurementHash{value: msg.value}( + data.teeType, + data.teeReportType, + data.cloudType, + data.teeAttestationReport, + data.workloadCollaterals + ); - if (pubKey.length != _ECDSA_KEY_LENGTH) { - revert InvalidECDSAPubKey(); - } + require(_goldenMeasurements[measurementHash].valid, InvalidMeasurement()); - // slither-disable-next-line uninitialized-state-variables - bool isValid = ENCLAVE_VERIFIER.verifyEvidence({ - blockNumber: blockNumber, - raveCommitment: keccak256(pubKey), - mrenclave: _mrenclave, - mrsigner: _mrsigner, - evidence: evidence - }); + bytes32 expectedCommitment = keccak256(abi.encodePacked(pubKey, blockhash(blockNumber))); + require(bytes32(tpmExtraData) == expectedCommitment, CommitmentMismatch()); - if (!isValid) { - revert InvalidRAVE(); - } + // Register guardian + address guardian = msg.sender; // pubKey[1:] means we need to strip the first byte '0x' if we want to get the correct address address computedAddress = address(uint160(uint256(keccak256(pubKey[1:])))); @@ -382,22 +375,15 @@ contract GuardianModule is AccessManaged, IGuardianModule { /** * @inheritdoc IGuardianModule */ - function getMrenclave() external view returns (bytes32) { - return _mrenclave; - } - - /** - * @inheritdoc IGuardianModule - */ - function getMrsigner() external view returns (bytes32) { - return _mrsigner; + function isGuardian(address account) external view returns (bool) { + return _guardians.contains(account); } /** * @inheritdoc IGuardianModule */ - function isGuardian(address account) external view returns (bool) { - return _guardians.contains(account); + function getGoldenMeasurement(bytes32 hash) external view returns (GoldenMeasurementInfo memory) { + return _goldenMeasurements[hash]; } function _addGuardian(address newGuardian) internal { diff --git a/mainnet-contracts/src/interface/IGuardianModule.sol b/mainnet-contracts/src/interface/IGuardianModule.sol index 7958f090..f9a78e8f 100644 --- a/mainnet-contracts/src/interface/IGuardianModule.sol +++ b/mainnet-contracts/src/interface/IGuardianModule.sol @@ -4,6 +4,7 @@ pragma solidity >=0.8.0 <0.9.0; import { RaveEvidence } from "../struct/RaveEvidence.sol"; import { IEnclaveVerifier } from "../EnclaveVerifier.sol"; import { StoppedValidatorInfo } from "../struct/StoppedValidatorInfo.sol"; +import { TdxRegistrationData, GoldenMeasurementInfo } from "../struct/GuardianModuleStructs.sol"; /** * @title IGuardianModule interface @@ -16,18 +17,30 @@ interface IGuardianModule { */ error InvalidECDSAPubKey(); - /** - * @notice Thrown when the RAVE evidence is not valid - * @dev Signature "0x2b3c629b" - */ - error InvalidRAVE(); - /** * @notice Thrown if the threshold value is not valid * @dev Signature "0x651a749b" */ error InvalidThreshold(uint256 threshold); + /** + * @notice Thrown if the data is not valid + * @dev Signature "0x5cb045db" + */ + error InvalidData(); + + /** + * @notice Thrown if the GoldenMeasurement is not valid + * @dev Signature "0x69e9d3ba" + */ + error InvalidMeasurement(); + + /** + * @notice Thrown if the Commitment does not match the workload verifier + * @dev Signature "0x5054097b" + */ + error CommitmentMismatch(); + /** * @notice Emitted when the ejection threshold is changed * @param oldThreshold is the old threshold value @@ -68,16 +81,19 @@ interface IGuardianModule { event RotatedGuardianKey(address guardian, address guardianEnclave, bytes pubKey); /** - * @notice Emitted when the mrenclave value is changed - * @dev Signature "0x1ff2c57ef9a384cea0c482d61fec8d708967d266f03266e301c6786f7209904a" + * @notice Emitted when a new GoldenMeasurement is registered + * @dev 0xe5cf28b6abd2dfc43e26d77ce57814cc723f1ee29925cd92112ea764eb1e6775 + * @param hash id of the GoldenMeasurement + * @param info data of the GoldenMeasurement */ - event MrEnclaveChanged(bytes32 oldMrEnclave, bytes32 newMrEnclave); + event GoldenMeasurementRegistered(bytes32 hash, GoldenMeasurementInfo info); /** - * @notice Emitted when the mrsigner value is changed - * @dev Signature "0x1a1fe271c5533136fccd1c6df515ca1f227d95822bfe78b9dd93debf3d709ae6" + * @notice Emitted when a GoldenMeasurement is deregistered + * @dev 0x3b86a29684cb98125d16491ad1dd1d2c52f8446ba9ba6ef696cef58743d8fa84 + * @param hash id of the GoldenMeasurement */ - event MrSignerChanged(bytes32 oldMrSigner, bytes32 newMrSigner); + event GoldenMeasurementDeregistered(bytes32 hash); /** * @notice Returns the enclave address registered to `guardian` @@ -94,9 +110,17 @@ interface IGuardianModule { function getEjectionThreshold() external view returns (uint256); /** - * @notice Sets the values for mrEnclave and mrSigner to `newMrenclave` and `newMrsigner` + * @notice Registers Golden Measurement + * @param hash id of the Golden Measurement + * @param info Info of the Golden Measurement */ - function setGuardianEnclaveMeasurements(bytes32 newMrenclave, bytes32 newMrsigner) external; + function registerGoldenMeasurement(bytes32 hash, GoldenMeasurementInfo calldata info) external; + + /** + * @notice Deregisters Golden Measurement + * @param hash id of the Golden Measurement + */ + function deregisterGoldenMeasurement(bytes32 hash) external; /** * @notice Validates the update of the number of validators @@ -107,11 +131,6 @@ interface IGuardianModule { bytes[] calldata guardianEOASignatures ) external view; - /** - * @notice Returns the enclave verifier - */ - function ENCLAVE_VERIFIER() external view returns (IEnclaveVerifier); - /** * @notice Validates the batch withdrawals calldata * @dev The order of the signatures is important @@ -220,12 +239,14 @@ interface IGuardianModule { /** * @notice Rotates guardian's key - * @dev If he caller is not a valid guardian or if the RAVE evidence is not valid the tx will revert + * @dev If he caller is not a valid guardian or if the TdxRegistrationData is not valid the tx will revert * @param blockNumber is the block number * @param pubKey is the public key of the new signature - * @param evidence is the RAVE evidence + * @param data TdxRegistrationData to verify */ - function rotateGuardianKey(uint256 blockNumber, bytes calldata pubKey, RaveEvidence calldata evidence) external; + function rotateGuardianKey(uint256 blockNumber, bytes calldata pubKey, TdxRegistrationData calldata data) + external + payable; /** * @notice Returns the guardians enclave addresses @@ -245,12 +266,10 @@ interface IGuardianModule { function isGuardian(address account) external view returns (bool); /** - * @notice Returns the mrenclave value + * @notice Returns the info of a GoldenMeasurement + * @param hash id of the GoldenMeasurement + * @return Info of the GoldenMeasurement */ - function getMrenclave() external view returns (bytes32); + function getGoldenMeasurement(bytes32 hash) external view returns (GoldenMeasurementInfo memory); - /** - * @notice Returns the mrsigner value - */ - function getMrsigner() external view returns (bytes32); } diff --git a/mainnet-contracts/src/struct/GuardianModuleStructs.sol b/mainnet-contracts/src/struct/GuardianModuleStructs.sol new file mode 100644 index 00000000..d4ba6821 --- /dev/null +++ b/mainnet-contracts/src/struct/GuardianModuleStructs.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.8.0 <0.9.0; + +import { TEEType, TeeReportType, CloudType } from "@automata-network/automata-tee-workload-measurement/lib/LibTEE.sol"; +import { WorkloadCollaterals } from "@automata-network/automata-tee-workload-measurement/interfaces/IWorkloadVerifier.sol"; + +/** + * @dev Tdx Registration Data + */ +struct TdxRegistrationData { + TEEType teeType; + TeeReportType teeReportType; + CloudType cloudType; + bytes teeAttestationReport; + WorkloadCollaterals workloadCollaterals; +} + +/** + * @dev Golden Measurement Info + */ +struct GoldenMeasurementInfo { + bool valid; + TEEType teeType; + CloudType cloudType; + string tag; // e.g., "guardian-v1.0.0" +} + +/** + * @dev Enclave data + * The guardian doesn't know the Secret Key of an enclave wallet + */ +struct GuardianData { + bytes enclavePubKey; + address enclaveAddress; +} From d236d0fd51e589d941dea2e4612f00bdd8e44af7 Mon Sep 17 00:00:00 2001 From: Eladio Date: Thu, 29 Jan 2026 11:10:20 +0100 Subject: [PATCH 13/51] Removed references to enclave and rave --- .../lib/automata-tee-workload-measurement | 1 + mainnet-contracts/package.json | 1 - mainnet-contracts/pnpm-lock.yaml | 2604 +++++++++++------ mainnet-contracts/src/EnclaveVerifier.sol | 105 - mainnet-contracts/src/GuardianModule.sol | 2 - .../src/interface/IEnclaveVerifier.sol | 63 - mainnet-contracts/src/struct/RaveEvidence.sol | 11 - yarn.lock | 4 - 8 files changed, 1772 insertions(+), 1019 deletions(-) create mode 160000 mainnet-contracts/lib/automata-tee-workload-measurement delete mode 100644 mainnet-contracts/src/EnclaveVerifier.sol delete mode 100644 mainnet-contracts/src/interface/IEnclaveVerifier.sol delete mode 100644 mainnet-contracts/src/struct/RaveEvidence.sol diff --git a/mainnet-contracts/lib/automata-tee-workload-measurement b/mainnet-contracts/lib/automata-tee-workload-measurement new file mode 160000 index 00000000..c3bcd68f --- /dev/null +++ b/mainnet-contracts/lib/automata-tee-workload-measurement @@ -0,0 +1 @@ +Subproject commit c3bcd68f4b887f86374cc47b31041bf2d667e7d3 diff --git a/mainnet-contracts/package.json b/mainnet-contracts/package.json index c07cd8b0..1358b40f 100644 --- a/mainnet-contracts/package.json +++ b/mainnet-contracts/package.json @@ -16,7 +16,6 @@ "@openzeppelin/contracts-upgradeable": "5.0.1", "l2-contracts": "*", "murky": "https://github.com/dmfxyz/murky.git", - "rave": "https://github.com/PufferFinance/rave.git#57ce268", "solidity-bytes-utils": "^0.8.4", "solidity-stringutils": "https://github.com/Arachnid/solidity-stringutils" }, diff --git a/mainnet-contracts/pnpm-lock.yaml b/mainnet-contracts/pnpm-lock.yaml index 3e7a801f..f8f31c49 100644 --- a/mainnet-contracts/pnpm-lock.yaml +++ b/mainnet-contracts/pnpm-lock.yaml @@ -1,37 +1,34 @@ -lockfileVersion: '6.0' +lockfileVersion: "6.0" settings: autoInstallPeers: true excludeLinksFromLockfile: false dependencies: - '@layerzerolabs/lz-evm-messagelib-v2': + "@layerzerolabs/lz-evm-messagelib-v2": specifier: ^3.0.75 version: 3.0.110(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.110)(@layerzerolabs/lz-evm-v1-0.7@3.0.110)(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.4) - '@layerzerolabs/lz-evm-protocol-v2': + "@layerzerolabs/lz-evm-protocol-v2": specifier: ^3.0.75 version: 3.0.110(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.4) - '@layerzerolabs/lz-evm-v1-0.7': + "@layerzerolabs/lz-evm-v1-0.7": specifier: ^3.0.75 version: 3.0.110(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4) - '@layerzerolabs/oapp-evm': + "@layerzerolabs/oapp-evm": specifier: ^0.3.2 version: 0.3.2(@layerzerolabs/lz-evm-messagelib-v2@3.0.110)(@layerzerolabs/lz-evm-protocol-v2@3.0.110)(@layerzerolabs/lz-evm-v1-0.7@3.0.110)(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1) - '@layerzerolabs/oft-evm': + "@layerzerolabs/oft-evm": specifier: ^3.1.3 version: 3.1.4(@layerzerolabs/lz-evm-messagelib-v2@3.0.110)(@layerzerolabs/lz-evm-protocol-v2@3.0.110)(@layerzerolabs/lz-evm-v1-0.7@3.0.110)(@layerzerolabs/oapp-evm@0.3.2)(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1) - '@openzeppelin/contracts': + "@openzeppelin/contracts": specifier: 5.0.1 version: 5.0.1 - '@openzeppelin/contracts-upgradeable': + "@openzeppelin/contracts-upgradeable": specifier: 5.0.1 version: 5.0.1(@openzeppelin/contracts@5.0.1) murky: specifier: https://github.com/dmfxyz/murky.git version: github.com/dmfxyz/murky/991e371eb1dfa9f86701869eb08ec4e98c3cc0b0 - rave: - specifier: https://github.com/PufferFinance/rave.git#57ce268 - version: github.com/PufferFinance/rave/57ce268 solidity-bytes-utils: specifier: ^0.8.4 version: 0.8.4 @@ -40,13 +37,13 @@ dependencies: version: github.com/Arachnid/solidity-stringutils/4b2fcc43fa0426e19ce88b1f1ec16f5903a2e461 devDependencies: - '@crytic/properties': + "@crytic/properties": specifier: https://github.com/crytic/properties#f1ff61b version: github.com/crytic/properties/f1ff61b - '@layerzerolabs/test-devtools-evm-foundry': + "@layerzerolabs/test-devtools-evm-foundry": specifier: ^6.0.3 version: 6.0.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.110)(@layerzerolabs/lz-evm-protocol-v2@3.0.110)(@layerzerolabs/lz-evm-v1-0.7@3.0.110)(@layerzerolabs/oapp-evm@0.3.2)(@layerzerolabs/oft-evm@3.1.4)(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1) - '@prb/test': + "@prb/test": specifier: 0.6.4 version: 0.6.4 erc4626-tests: @@ -63,80 +60,100 @@ devDependencies: version: 5.2.0 packages: - /@axelar-network/axelar-gmp-sdk-solidity@5.10.0: - resolution: {integrity: sha512-s8SImALvYB+5AeiT3tbfWNBI2Mhqw1x91i/zM3DNpVUCnAR2HKtsB9T84KnUn/OJjOVgb4h0lv7q9smeYniRPw==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-s8SImALvYB+5AeiT3tbfWNBI2Mhqw1x91i/zM3DNpVUCnAR2HKtsB9T84KnUn/OJjOVgb4h0lv7q9smeYniRPw==, + } + engines: { node: ">=18" } /@babel/code-frame@7.27.1: - resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} - engines: {node: '>=6.9.0'} + resolution: + { + integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==, + } + engines: { node: ">=6.9.0" } dependencies: - '@babel/helper-validator-identifier': 7.27.1 + "@babel/helper-validator-identifier": 7.27.1 js-tokens: 4.0.0 picocolors: 1.1.1 dev: true /@babel/helper-validator-identifier@7.27.1: - resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} - engines: {node: '>=6.9.0'} + resolution: + { + integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==, + } + engines: { node: ">=6.9.0" } dev: true /@chainlink/contracts-ccip@0.7.6(ethers@5.8.0): - resolution: {integrity: sha512-yNbCBFpLs3R+ALymto9dQYKz3vatnjqYGu1pnMD0i2fHEMthiXe0+otaNCGNht6n8k7ruNaA0DNpz3F+2jHQXw==} - dependencies: - '@eth-optimism/contracts': 0.5.40(ethers@5.8.0) - '@openzeppelin/contracts': 4.3.3 - '@openzeppelin/contracts-upgradeable-4.7.3': /@openzeppelin/contracts-upgradeable@4.7.3 - '@openzeppelin/contracts-v0.7': /@openzeppelin/contracts@3.4.2 + resolution: + { + integrity: sha512-yNbCBFpLs3R+ALymto9dQYKz3vatnjqYGu1pnMD0i2fHEMthiXe0+otaNCGNht6n8k7ruNaA0DNpz3F+2jHQXw==, + } + dependencies: + "@eth-optimism/contracts": 0.5.40(ethers@5.8.0) + "@openzeppelin/contracts": 4.3.3 + "@openzeppelin/contracts-upgradeable-4.7.3": /@openzeppelin/contracts-upgradeable@4.7.3 + "@openzeppelin/contracts-v0.7": /@openzeppelin/contracts@3.4.2 transitivePeerDependencies: - bufferutil - ethers - utf-8-validate /@eth-optimism/contracts@0.5.40(ethers@5.8.0): - resolution: {integrity: sha512-MrzV0nvsymfO/fursTB7m/KunkPsCndltVgfdHaT1Aj5Vi6R/doKIGGkOofHX+8B6VMZpuZosKCMQ5lQuqjt8w==} + resolution: + { + integrity: sha512-MrzV0nvsymfO/fursTB7m/KunkPsCndltVgfdHaT1Aj5Vi6R/doKIGGkOofHX+8B6VMZpuZosKCMQ5lQuqjt8w==, + } peerDependencies: ethers: ^5 dependencies: - '@eth-optimism/core-utils': 0.12.0 - '@ethersproject/abstract-provider': 5.8.0 - '@ethersproject/abstract-signer': 5.8.0 + "@eth-optimism/core-utils": 0.12.0 + "@ethersproject/abstract-provider": 5.8.0 + "@ethersproject/abstract-signer": 5.8.0 ethers: 5.8.0 transitivePeerDependencies: - bufferutil - utf-8-validate /@eth-optimism/contracts@0.6.0(ethers@5.8.0): - resolution: {integrity: sha512-vQ04wfG9kMf1Fwy3FEMqH2QZbgS0gldKhcBeBUPfO8zu68L61VI97UDXmsMQXzTsEAxK8HnokW3/gosl4/NW3w==} + resolution: + { + integrity: sha512-vQ04wfG9kMf1Fwy3FEMqH2QZbgS0gldKhcBeBUPfO8zu68L61VI97UDXmsMQXzTsEAxK8HnokW3/gosl4/NW3w==, + } peerDependencies: ethers: ^5 dependencies: - '@eth-optimism/core-utils': 0.12.0 - '@ethersproject/abstract-provider': 5.8.0 - '@ethersproject/abstract-signer': 5.8.0 + "@eth-optimism/core-utils": 0.12.0 + "@ethersproject/abstract-provider": 5.8.0 + "@ethersproject/abstract-signer": 5.8.0 ethers: 5.8.0 transitivePeerDependencies: - bufferutil - utf-8-validate /@eth-optimism/core-utils@0.12.0: - resolution: {integrity: sha512-qW+7LZYCz7i8dRa7SRlUKIo1VBU8lvN0HeXCxJR+z+xtMzMQpPds20XJNCMclszxYQHkXY00fOT6GvFw9ZL6nw==} - dependencies: - '@ethersproject/abi': 5.8.0 - '@ethersproject/abstract-provider': 5.8.0 - '@ethersproject/address': 5.8.0 - '@ethersproject/bignumber': 5.8.0 - '@ethersproject/bytes': 5.8.0 - '@ethersproject/constants': 5.8.0 - '@ethersproject/contracts': 5.8.0 - '@ethersproject/hash': 5.8.0 - '@ethersproject/keccak256': 5.8.0 - '@ethersproject/properties': 5.8.0 - '@ethersproject/providers': 5.8.0 - '@ethersproject/rlp': 5.8.0 - '@ethersproject/transactions': 5.8.0 - '@ethersproject/web': 5.8.0 + resolution: + { + integrity: sha512-qW+7LZYCz7i8dRa7SRlUKIo1VBU8lvN0HeXCxJR+z+xtMzMQpPds20XJNCMclszxYQHkXY00fOT6GvFw9ZL6nw==, + } + dependencies: + "@ethersproject/abi": 5.8.0 + "@ethersproject/abstract-provider": 5.8.0 + "@ethersproject/address": 5.8.0 + "@ethersproject/bignumber": 5.8.0 + "@ethersproject/bytes": 5.8.0 + "@ethersproject/constants": 5.8.0 + "@ethersproject/contracts": 5.8.0 + "@ethersproject/hash": 5.8.0 + "@ethersproject/keccak256": 5.8.0 + "@ethersproject/properties": 5.8.0 + "@ethersproject/providers": 5.8.0 + "@ethersproject/rlp": 5.8.0 + "@ethersproject/transactions": 5.8.0 + "@ethersproject/web": 5.8.0 bufio: 1.2.3 chai: 4.5.0 transitivePeerDependencies: @@ -144,181 +161,238 @@ packages: - utf-8-validate /@ethersproject/abi@5.8.0: - resolution: {integrity: sha512-b9YS/43ObplgyV6SlyQsG53/vkSal0MNA1fskSC4mbnCMi8R+NkcH8K9FPYNESf6jUefBUniE4SOKms0E/KK1Q==} - dependencies: - '@ethersproject/address': 5.8.0 - '@ethersproject/bignumber': 5.8.0 - '@ethersproject/bytes': 5.8.0 - '@ethersproject/constants': 5.8.0 - '@ethersproject/hash': 5.8.0 - '@ethersproject/keccak256': 5.8.0 - '@ethersproject/logger': 5.8.0 - '@ethersproject/properties': 5.8.0 - '@ethersproject/strings': 5.8.0 + resolution: + { + integrity: sha512-b9YS/43ObplgyV6SlyQsG53/vkSal0MNA1fskSC4mbnCMi8R+NkcH8K9FPYNESf6jUefBUniE4SOKms0E/KK1Q==, + } + dependencies: + "@ethersproject/address": 5.8.0 + "@ethersproject/bignumber": 5.8.0 + "@ethersproject/bytes": 5.8.0 + "@ethersproject/constants": 5.8.0 + "@ethersproject/hash": 5.8.0 + "@ethersproject/keccak256": 5.8.0 + "@ethersproject/logger": 5.8.0 + "@ethersproject/properties": 5.8.0 + "@ethersproject/strings": 5.8.0 /@ethersproject/abstract-provider@5.8.0: - resolution: {integrity: sha512-wC9SFcmh4UK0oKuLJQItoQdzS/qZ51EJegK6EmAWlh+OptpQ/npECOR3QqECd8iGHC0RJb4WKbVdSfif4ammrg==} - dependencies: - '@ethersproject/bignumber': 5.8.0 - '@ethersproject/bytes': 5.8.0 - '@ethersproject/logger': 5.8.0 - '@ethersproject/networks': 5.8.0 - '@ethersproject/properties': 5.8.0 - '@ethersproject/transactions': 5.8.0 - '@ethersproject/web': 5.8.0 + resolution: + { + integrity: sha512-wC9SFcmh4UK0oKuLJQItoQdzS/qZ51EJegK6EmAWlh+OptpQ/npECOR3QqECd8iGHC0RJb4WKbVdSfif4ammrg==, + } + dependencies: + "@ethersproject/bignumber": 5.8.0 + "@ethersproject/bytes": 5.8.0 + "@ethersproject/logger": 5.8.0 + "@ethersproject/networks": 5.8.0 + "@ethersproject/properties": 5.8.0 + "@ethersproject/transactions": 5.8.0 + "@ethersproject/web": 5.8.0 /@ethersproject/abstract-signer@5.8.0: - resolution: {integrity: sha512-N0XhZTswXcmIZQdYtUnd79VJzvEwXQw6PK0dTl9VoYrEBxxCPXqS0Eod7q5TNKRxe1/5WUMuR0u0nqTF/avdCA==} + resolution: + { + integrity: sha512-N0XhZTswXcmIZQdYtUnd79VJzvEwXQw6PK0dTl9VoYrEBxxCPXqS0Eod7q5TNKRxe1/5WUMuR0u0nqTF/avdCA==, + } dependencies: - '@ethersproject/abstract-provider': 5.8.0 - '@ethersproject/bignumber': 5.8.0 - '@ethersproject/bytes': 5.8.0 - '@ethersproject/logger': 5.8.0 - '@ethersproject/properties': 5.8.0 + "@ethersproject/abstract-provider": 5.8.0 + "@ethersproject/bignumber": 5.8.0 + "@ethersproject/bytes": 5.8.0 + "@ethersproject/logger": 5.8.0 + "@ethersproject/properties": 5.8.0 /@ethersproject/address@5.8.0: - resolution: {integrity: sha512-GhH/abcC46LJwshoN+uBNoKVFPxUuZm6dA257z0vZkKmU1+t8xTn8oK7B9qrj8W2rFRMch4gbJl6PmVxjxBEBA==} + resolution: + { + integrity: sha512-GhH/abcC46LJwshoN+uBNoKVFPxUuZm6dA257z0vZkKmU1+t8xTn8oK7B9qrj8W2rFRMch4gbJl6PmVxjxBEBA==, + } dependencies: - '@ethersproject/bignumber': 5.8.0 - '@ethersproject/bytes': 5.8.0 - '@ethersproject/keccak256': 5.8.0 - '@ethersproject/logger': 5.8.0 - '@ethersproject/rlp': 5.8.0 + "@ethersproject/bignumber": 5.8.0 + "@ethersproject/bytes": 5.8.0 + "@ethersproject/keccak256": 5.8.0 + "@ethersproject/logger": 5.8.0 + "@ethersproject/rlp": 5.8.0 /@ethersproject/base64@5.8.0: - resolution: {integrity: sha512-lN0oIwfkYj9LbPx4xEkie6rAMJtySbpOAFXSDVQaBnAzYfB4X2Qr+FXJGxMoc3Bxp2Sm8OwvzMrywxyw0gLjIQ==} + resolution: + { + integrity: sha512-lN0oIwfkYj9LbPx4xEkie6rAMJtySbpOAFXSDVQaBnAzYfB4X2Qr+FXJGxMoc3Bxp2Sm8OwvzMrywxyw0gLjIQ==, + } dependencies: - '@ethersproject/bytes': 5.8.0 + "@ethersproject/bytes": 5.8.0 /@ethersproject/basex@5.8.0: - resolution: {integrity: sha512-PIgTszMlDRmNwW9nhS6iqtVfdTAKosA7llYXNmGPw4YAI1PUyMv28988wAb41/gHF/WqGdoLv0erHaRcHRKW2Q==} + resolution: + { + integrity: sha512-PIgTszMlDRmNwW9nhS6iqtVfdTAKosA7llYXNmGPw4YAI1PUyMv28988wAb41/gHF/WqGdoLv0erHaRcHRKW2Q==, + } dependencies: - '@ethersproject/bytes': 5.8.0 - '@ethersproject/properties': 5.8.0 + "@ethersproject/bytes": 5.8.0 + "@ethersproject/properties": 5.8.0 /@ethersproject/bignumber@5.8.0: - resolution: {integrity: sha512-ZyaT24bHaSeJon2tGPKIiHszWjD/54Sz8t57Toch475lCLljC6MgPmxk7Gtzz+ddNN5LuHea9qhAe0x3D+uYPA==} + resolution: + { + integrity: sha512-ZyaT24bHaSeJon2tGPKIiHszWjD/54Sz8t57Toch475lCLljC6MgPmxk7Gtzz+ddNN5LuHea9qhAe0x3D+uYPA==, + } dependencies: - '@ethersproject/bytes': 5.8.0 - '@ethersproject/logger': 5.8.0 + "@ethersproject/bytes": 5.8.0 + "@ethersproject/logger": 5.8.0 bn.js: 5.2.2 /@ethersproject/bytes@5.8.0: - resolution: {integrity: sha512-vTkeohgJVCPVHu5c25XWaWQOZ4v+DkGoC42/TS2ond+PARCxTJvgTFUNDZovyQ/uAQ4EcpqqowKydcdmRKjg7A==} + resolution: + { + integrity: sha512-vTkeohgJVCPVHu5c25XWaWQOZ4v+DkGoC42/TS2ond+PARCxTJvgTFUNDZovyQ/uAQ4EcpqqowKydcdmRKjg7A==, + } dependencies: - '@ethersproject/logger': 5.8.0 + "@ethersproject/logger": 5.8.0 /@ethersproject/constants@5.8.0: - resolution: {integrity: sha512-wigX4lrf5Vu+axVTIvNsuL6YrV4O5AXl5ubcURKMEME5TnWBouUh0CDTWxZ2GpnRn1kcCgE7l8O5+VbV9QTTcg==} + resolution: + { + integrity: sha512-wigX4lrf5Vu+axVTIvNsuL6YrV4O5AXl5ubcURKMEME5TnWBouUh0CDTWxZ2GpnRn1kcCgE7l8O5+VbV9QTTcg==, + } dependencies: - '@ethersproject/bignumber': 5.8.0 + "@ethersproject/bignumber": 5.8.0 /@ethersproject/contracts@5.8.0: - resolution: {integrity: sha512-0eFjGz9GtuAi6MZwhb4uvUM216F38xiuR0yYCjKJpNfSEy4HUM8hvqqBj9Jmm0IUz8l0xKEhWwLIhPgxNY0yvQ==} - dependencies: - '@ethersproject/abi': 5.8.0 - '@ethersproject/abstract-provider': 5.8.0 - '@ethersproject/abstract-signer': 5.8.0 - '@ethersproject/address': 5.8.0 - '@ethersproject/bignumber': 5.8.0 - '@ethersproject/bytes': 5.8.0 - '@ethersproject/constants': 5.8.0 - '@ethersproject/logger': 5.8.0 - '@ethersproject/properties': 5.8.0 - '@ethersproject/transactions': 5.8.0 + resolution: + { + integrity: sha512-0eFjGz9GtuAi6MZwhb4uvUM216F38xiuR0yYCjKJpNfSEy4HUM8hvqqBj9Jmm0IUz8l0xKEhWwLIhPgxNY0yvQ==, + } + dependencies: + "@ethersproject/abi": 5.8.0 + "@ethersproject/abstract-provider": 5.8.0 + "@ethersproject/abstract-signer": 5.8.0 + "@ethersproject/address": 5.8.0 + "@ethersproject/bignumber": 5.8.0 + "@ethersproject/bytes": 5.8.0 + "@ethersproject/constants": 5.8.0 + "@ethersproject/logger": 5.8.0 + "@ethersproject/properties": 5.8.0 + "@ethersproject/transactions": 5.8.0 /@ethersproject/hash@5.8.0: - resolution: {integrity: sha512-ac/lBcTbEWW/VGJij0CNSw/wPcw9bSRgCB0AIBz8CvED/jfvDoV9hsIIiWfvWmFEi8RcXtlNwp2jv6ozWOsooA==} - dependencies: - '@ethersproject/abstract-signer': 5.8.0 - '@ethersproject/address': 5.8.0 - '@ethersproject/base64': 5.8.0 - '@ethersproject/bignumber': 5.8.0 - '@ethersproject/bytes': 5.8.0 - '@ethersproject/keccak256': 5.8.0 - '@ethersproject/logger': 5.8.0 - '@ethersproject/properties': 5.8.0 - '@ethersproject/strings': 5.8.0 + resolution: + { + integrity: sha512-ac/lBcTbEWW/VGJij0CNSw/wPcw9bSRgCB0AIBz8CvED/jfvDoV9hsIIiWfvWmFEi8RcXtlNwp2jv6ozWOsooA==, + } + dependencies: + "@ethersproject/abstract-signer": 5.8.0 + "@ethersproject/address": 5.8.0 + "@ethersproject/base64": 5.8.0 + "@ethersproject/bignumber": 5.8.0 + "@ethersproject/bytes": 5.8.0 + "@ethersproject/keccak256": 5.8.0 + "@ethersproject/logger": 5.8.0 + "@ethersproject/properties": 5.8.0 + "@ethersproject/strings": 5.8.0 /@ethersproject/hdnode@5.8.0: - resolution: {integrity: sha512-4bK1VF6E83/3/Im0ERnnUeWOY3P1BZml4ZD3wcH8Ys0/d1h1xaFt6Zc+Dh9zXf9TapGro0T4wvO71UTCp3/uoA==} - dependencies: - '@ethersproject/abstract-signer': 5.8.0 - '@ethersproject/basex': 5.8.0 - '@ethersproject/bignumber': 5.8.0 - '@ethersproject/bytes': 5.8.0 - '@ethersproject/logger': 5.8.0 - '@ethersproject/pbkdf2': 5.8.0 - '@ethersproject/properties': 5.8.0 - '@ethersproject/sha2': 5.8.0 - '@ethersproject/signing-key': 5.8.0 - '@ethersproject/strings': 5.8.0 - '@ethersproject/transactions': 5.8.0 - '@ethersproject/wordlists': 5.8.0 + resolution: + { + integrity: sha512-4bK1VF6E83/3/Im0ERnnUeWOY3P1BZml4ZD3wcH8Ys0/d1h1xaFt6Zc+Dh9zXf9TapGro0T4wvO71UTCp3/uoA==, + } + dependencies: + "@ethersproject/abstract-signer": 5.8.0 + "@ethersproject/basex": 5.8.0 + "@ethersproject/bignumber": 5.8.0 + "@ethersproject/bytes": 5.8.0 + "@ethersproject/logger": 5.8.0 + "@ethersproject/pbkdf2": 5.8.0 + "@ethersproject/properties": 5.8.0 + "@ethersproject/sha2": 5.8.0 + "@ethersproject/signing-key": 5.8.0 + "@ethersproject/strings": 5.8.0 + "@ethersproject/transactions": 5.8.0 + "@ethersproject/wordlists": 5.8.0 /@ethersproject/json-wallets@5.8.0: - resolution: {integrity: sha512-HxblNck8FVUtNxS3VTEYJAcwiKYsBIF77W15HufqlBF9gGfhmYOJtYZp8fSDZtn9y5EaXTE87zDwzxRoTFk11w==} - dependencies: - '@ethersproject/abstract-signer': 5.8.0 - '@ethersproject/address': 5.8.0 - '@ethersproject/bytes': 5.8.0 - '@ethersproject/hdnode': 5.8.0 - '@ethersproject/keccak256': 5.8.0 - '@ethersproject/logger': 5.8.0 - '@ethersproject/pbkdf2': 5.8.0 - '@ethersproject/properties': 5.8.0 - '@ethersproject/random': 5.8.0 - '@ethersproject/strings': 5.8.0 - '@ethersproject/transactions': 5.8.0 + resolution: + { + integrity: sha512-HxblNck8FVUtNxS3VTEYJAcwiKYsBIF77W15HufqlBF9gGfhmYOJtYZp8fSDZtn9y5EaXTE87zDwzxRoTFk11w==, + } + dependencies: + "@ethersproject/abstract-signer": 5.8.0 + "@ethersproject/address": 5.8.0 + "@ethersproject/bytes": 5.8.0 + "@ethersproject/hdnode": 5.8.0 + "@ethersproject/keccak256": 5.8.0 + "@ethersproject/logger": 5.8.0 + "@ethersproject/pbkdf2": 5.8.0 + "@ethersproject/properties": 5.8.0 + "@ethersproject/random": 5.8.0 + "@ethersproject/strings": 5.8.0 + "@ethersproject/transactions": 5.8.0 aes-js: 3.0.0 scrypt-js: 3.0.1 /@ethersproject/keccak256@5.8.0: - resolution: {integrity: sha512-A1pkKLZSz8pDaQ1ftutZoaN46I6+jvuqugx5KYNeQOPqq+JZ0Txm7dlWesCHB5cndJSu5vP2VKptKf7cksERng==} + resolution: + { + integrity: sha512-A1pkKLZSz8pDaQ1ftutZoaN46I6+jvuqugx5KYNeQOPqq+JZ0Txm7dlWesCHB5cndJSu5vP2VKptKf7cksERng==, + } dependencies: - '@ethersproject/bytes': 5.8.0 + "@ethersproject/bytes": 5.8.0 js-sha3: 0.8.0 /@ethersproject/logger@5.8.0: - resolution: {integrity: sha512-Qe6knGmY+zPPWTC+wQrpitodgBfH7XoceCGL5bJVejmH+yCS3R8jJm8iiWuvWbG76RUmyEG53oqv6GMVWqunjA==} + resolution: + { + integrity: sha512-Qe6knGmY+zPPWTC+wQrpitodgBfH7XoceCGL5bJVejmH+yCS3R8jJm8iiWuvWbG76RUmyEG53oqv6GMVWqunjA==, + } /@ethersproject/networks@5.8.0: - resolution: {integrity: sha512-egPJh3aPVAzbHwq8DD7Po53J4OUSsA1MjQp8Vf/OZPav5rlmWUaFLiq8cvQiGK0Z5K6LYzm29+VA/p4RL1FzNg==} + resolution: + { + integrity: sha512-egPJh3aPVAzbHwq8DD7Po53J4OUSsA1MjQp8Vf/OZPav5rlmWUaFLiq8cvQiGK0Z5K6LYzm29+VA/p4RL1FzNg==, + } dependencies: - '@ethersproject/logger': 5.8.0 + "@ethersproject/logger": 5.8.0 /@ethersproject/pbkdf2@5.8.0: - resolution: {integrity: sha512-wuHiv97BrzCmfEaPbUFpMjlVg/IDkZThp9Ri88BpjRleg4iePJaj2SW8AIyE8cXn5V1tuAaMj6lzvsGJkGWskg==} + resolution: + { + integrity: sha512-wuHiv97BrzCmfEaPbUFpMjlVg/IDkZThp9Ri88BpjRleg4iePJaj2SW8AIyE8cXn5V1tuAaMj6lzvsGJkGWskg==, + } dependencies: - '@ethersproject/bytes': 5.8.0 - '@ethersproject/sha2': 5.8.0 + "@ethersproject/bytes": 5.8.0 + "@ethersproject/sha2": 5.8.0 /@ethersproject/properties@5.8.0: - resolution: {integrity: sha512-PYuiEoQ+FMaZZNGrStmN7+lWjlsoufGIHdww7454FIaGdbe/p5rnaCXTr5MtBYl3NkeoVhHZuyzChPeGeKIpQw==} + resolution: + { + integrity: sha512-PYuiEoQ+FMaZZNGrStmN7+lWjlsoufGIHdww7454FIaGdbe/p5rnaCXTr5MtBYl3NkeoVhHZuyzChPeGeKIpQw==, + } dependencies: - '@ethersproject/logger': 5.8.0 + "@ethersproject/logger": 5.8.0 /@ethersproject/providers@5.8.0: - resolution: {integrity: sha512-3Il3oTzEx3o6kzcg9ZzbE+oCZYyY+3Zh83sKkn4s1DZfTUjIegHnN2Cm0kbn9YFy45FDVcuCLLONhU7ny0SsCw==} - dependencies: - '@ethersproject/abstract-provider': 5.8.0 - '@ethersproject/abstract-signer': 5.8.0 - '@ethersproject/address': 5.8.0 - '@ethersproject/base64': 5.8.0 - '@ethersproject/basex': 5.8.0 - '@ethersproject/bignumber': 5.8.0 - '@ethersproject/bytes': 5.8.0 - '@ethersproject/constants': 5.8.0 - '@ethersproject/hash': 5.8.0 - '@ethersproject/logger': 5.8.0 - '@ethersproject/networks': 5.8.0 - '@ethersproject/properties': 5.8.0 - '@ethersproject/random': 5.8.0 - '@ethersproject/rlp': 5.8.0 - '@ethersproject/sha2': 5.8.0 - '@ethersproject/strings': 5.8.0 - '@ethersproject/transactions': 5.8.0 - '@ethersproject/web': 5.8.0 + resolution: + { + integrity: sha512-3Il3oTzEx3o6kzcg9ZzbE+oCZYyY+3Zh83sKkn4s1DZfTUjIegHnN2Cm0kbn9YFy45FDVcuCLLONhU7ny0SsCw==, + } + dependencies: + "@ethersproject/abstract-provider": 5.8.0 + "@ethersproject/abstract-signer": 5.8.0 + "@ethersproject/address": 5.8.0 + "@ethersproject/base64": 5.8.0 + "@ethersproject/basex": 5.8.0 + "@ethersproject/bignumber": 5.8.0 + "@ethersproject/bytes": 5.8.0 + "@ethersproject/constants": 5.8.0 + "@ethersproject/hash": 5.8.0 + "@ethersproject/logger": 5.8.0 + "@ethersproject/networks": 5.8.0 + "@ethersproject/properties": 5.8.0 + "@ethersproject/random": 5.8.0 + "@ethersproject/rlp": 5.8.0 + "@ethersproject/sha2": 5.8.0 + "@ethersproject/strings": 5.8.0 + "@ethersproject/transactions": 5.8.0 + "@ethersproject/web": 5.8.0 bech32: 1.1.4 ws: 8.18.0 transitivePeerDependencies: @@ -326,342 +400,468 @@ packages: - utf-8-validate /@ethersproject/random@5.8.0: - resolution: {integrity: sha512-E4I5TDl7SVqyg4/kkA/qTfuLWAQGXmSOgYyO01So8hLfwgKvYK5snIlzxJMk72IFdG/7oh8yuSqY2KX7MMwg+A==} + resolution: + { + integrity: sha512-E4I5TDl7SVqyg4/kkA/qTfuLWAQGXmSOgYyO01So8hLfwgKvYK5snIlzxJMk72IFdG/7oh8yuSqY2KX7MMwg+A==, + } dependencies: - '@ethersproject/bytes': 5.8.0 - '@ethersproject/logger': 5.8.0 + "@ethersproject/bytes": 5.8.0 + "@ethersproject/logger": 5.8.0 /@ethersproject/rlp@5.8.0: - resolution: {integrity: sha512-LqZgAznqDbiEunaUvykH2JAoXTT9NV0Atqk8rQN9nx9SEgThA/WMx5DnW8a9FOufo//6FZOCHZ+XiClzgbqV9Q==} + resolution: + { + integrity: sha512-LqZgAznqDbiEunaUvykH2JAoXTT9NV0Atqk8rQN9nx9SEgThA/WMx5DnW8a9FOufo//6FZOCHZ+XiClzgbqV9Q==, + } dependencies: - '@ethersproject/bytes': 5.8.0 - '@ethersproject/logger': 5.8.0 + "@ethersproject/bytes": 5.8.0 + "@ethersproject/logger": 5.8.0 /@ethersproject/sha2@5.8.0: - resolution: {integrity: sha512-dDOUrXr9wF/YFltgTBYS0tKslPEKr6AekjqDW2dbn1L1xmjGR+9GiKu4ajxovnrDbwxAKdHjW8jNcwfz8PAz4A==} + resolution: + { + integrity: sha512-dDOUrXr9wF/YFltgTBYS0tKslPEKr6AekjqDW2dbn1L1xmjGR+9GiKu4ajxovnrDbwxAKdHjW8jNcwfz8PAz4A==, + } dependencies: - '@ethersproject/bytes': 5.8.0 - '@ethersproject/logger': 5.8.0 + "@ethersproject/bytes": 5.8.0 + "@ethersproject/logger": 5.8.0 hash.js: 1.1.7 /@ethersproject/signing-key@5.8.0: - resolution: {integrity: sha512-LrPW2ZxoigFi6U6aVkFN/fa9Yx/+4AtIUe4/HACTvKJdhm0eeb107EVCIQcrLZkxaSIgc/eCrX8Q1GtbH+9n3w==} - dependencies: - '@ethersproject/bytes': 5.8.0 - '@ethersproject/logger': 5.8.0 - '@ethersproject/properties': 5.8.0 + resolution: + { + integrity: sha512-LrPW2ZxoigFi6U6aVkFN/fa9Yx/+4AtIUe4/HACTvKJdhm0eeb107EVCIQcrLZkxaSIgc/eCrX8Q1GtbH+9n3w==, + } + dependencies: + "@ethersproject/bytes": 5.8.0 + "@ethersproject/logger": 5.8.0 + "@ethersproject/properties": 5.8.0 bn.js: 5.2.2 elliptic: 6.6.1 hash.js: 1.1.7 /@ethersproject/solidity@5.8.0: - resolution: {integrity: sha512-4CxFeCgmIWamOHwYN9d+QWGxye9qQLilpgTU0XhYs1OahkclF+ewO+3V1U0mvpiuQxm5EHHmv8f7ClVII8EHsA==} - dependencies: - '@ethersproject/bignumber': 5.8.0 - '@ethersproject/bytes': 5.8.0 - '@ethersproject/keccak256': 5.8.0 - '@ethersproject/logger': 5.8.0 - '@ethersproject/sha2': 5.8.0 - '@ethersproject/strings': 5.8.0 + resolution: + { + integrity: sha512-4CxFeCgmIWamOHwYN9d+QWGxye9qQLilpgTU0XhYs1OahkclF+ewO+3V1U0mvpiuQxm5EHHmv8f7ClVII8EHsA==, + } + dependencies: + "@ethersproject/bignumber": 5.8.0 + "@ethersproject/bytes": 5.8.0 + "@ethersproject/keccak256": 5.8.0 + "@ethersproject/logger": 5.8.0 + "@ethersproject/sha2": 5.8.0 + "@ethersproject/strings": 5.8.0 /@ethersproject/strings@5.8.0: - resolution: {integrity: sha512-qWEAk0MAvl0LszjdfnZ2uC8xbR2wdv4cDabyHiBh3Cldq/T8dPH3V4BbBsAYJUeonwD+8afVXld274Ls+Y1xXg==} + resolution: + { + integrity: sha512-qWEAk0MAvl0LszjdfnZ2uC8xbR2wdv4cDabyHiBh3Cldq/T8dPH3V4BbBsAYJUeonwD+8afVXld274Ls+Y1xXg==, + } dependencies: - '@ethersproject/bytes': 5.8.0 - '@ethersproject/constants': 5.8.0 - '@ethersproject/logger': 5.8.0 + "@ethersproject/bytes": 5.8.0 + "@ethersproject/constants": 5.8.0 + "@ethersproject/logger": 5.8.0 /@ethersproject/transactions@5.8.0: - resolution: {integrity: sha512-UglxSDjByHG0TuU17bDfCemZ3AnKO2vYrL5/2n2oXvKzvb7Cz+W9gOWXKARjp2URVwcWlQlPOEQyAviKwT4AHg==} - dependencies: - '@ethersproject/address': 5.8.0 - '@ethersproject/bignumber': 5.8.0 - '@ethersproject/bytes': 5.8.0 - '@ethersproject/constants': 5.8.0 - '@ethersproject/keccak256': 5.8.0 - '@ethersproject/logger': 5.8.0 - '@ethersproject/properties': 5.8.0 - '@ethersproject/rlp': 5.8.0 - '@ethersproject/signing-key': 5.8.0 + resolution: + { + integrity: sha512-UglxSDjByHG0TuU17bDfCemZ3AnKO2vYrL5/2n2oXvKzvb7Cz+W9gOWXKARjp2URVwcWlQlPOEQyAviKwT4AHg==, + } + dependencies: + "@ethersproject/address": 5.8.0 + "@ethersproject/bignumber": 5.8.0 + "@ethersproject/bytes": 5.8.0 + "@ethersproject/constants": 5.8.0 + "@ethersproject/keccak256": 5.8.0 + "@ethersproject/logger": 5.8.0 + "@ethersproject/properties": 5.8.0 + "@ethersproject/rlp": 5.8.0 + "@ethersproject/signing-key": 5.8.0 /@ethersproject/units@5.8.0: - resolution: {integrity: sha512-lxq0CAnc5kMGIiWW4Mr041VT8IhNM+Pn5T3haO74XZWFulk7wH1Gv64HqE96hT4a7iiNMdOCFEBgaxWuk8ETKQ==} + resolution: + { + integrity: sha512-lxq0CAnc5kMGIiWW4Mr041VT8IhNM+Pn5T3haO74XZWFulk7wH1Gv64HqE96hT4a7iiNMdOCFEBgaxWuk8ETKQ==, + } dependencies: - '@ethersproject/bignumber': 5.8.0 - '@ethersproject/constants': 5.8.0 - '@ethersproject/logger': 5.8.0 + "@ethersproject/bignumber": 5.8.0 + "@ethersproject/constants": 5.8.0 + "@ethersproject/logger": 5.8.0 /@ethersproject/wallet@5.8.0: - resolution: {integrity: sha512-G+jnzmgg6UxurVKRKvw27h0kvG75YKXZKdlLYmAHeF32TGUzHkOFd7Zn6QHOTYRFWnfjtSSFjBowKo7vfrXzPA==} - dependencies: - '@ethersproject/abstract-provider': 5.8.0 - '@ethersproject/abstract-signer': 5.8.0 - '@ethersproject/address': 5.8.0 - '@ethersproject/bignumber': 5.8.0 - '@ethersproject/bytes': 5.8.0 - '@ethersproject/hash': 5.8.0 - '@ethersproject/hdnode': 5.8.0 - '@ethersproject/json-wallets': 5.8.0 - '@ethersproject/keccak256': 5.8.0 - '@ethersproject/logger': 5.8.0 - '@ethersproject/properties': 5.8.0 - '@ethersproject/random': 5.8.0 - '@ethersproject/signing-key': 5.8.0 - '@ethersproject/transactions': 5.8.0 - '@ethersproject/wordlists': 5.8.0 + resolution: + { + integrity: sha512-G+jnzmgg6UxurVKRKvw27h0kvG75YKXZKdlLYmAHeF32TGUzHkOFd7Zn6QHOTYRFWnfjtSSFjBowKo7vfrXzPA==, + } + dependencies: + "@ethersproject/abstract-provider": 5.8.0 + "@ethersproject/abstract-signer": 5.8.0 + "@ethersproject/address": 5.8.0 + "@ethersproject/bignumber": 5.8.0 + "@ethersproject/bytes": 5.8.0 + "@ethersproject/hash": 5.8.0 + "@ethersproject/hdnode": 5.8.0 + "@ethersproject/json-wallets": 5.8.0 + "@ethersproject/keccak256": 5.8.0 + "@ethersproject/logger": 5.8.0 + "@ethersproject/properties": 5.8.0 + "@ethersproject/random": 5.8.0 + "@ethersproject/signing-key": 5.8.0 + "@ethersproject/transactions": 5.8.0 + "@ethersproject/wordlists": 5.8.0 /@ethersproject/web@5.8.0: - resolution: {integrity: sha512-j7+Ksi/9KfGviws6Qtf9Q7KCqRhpwrYKQPs+JBA/rKVFF/yaWLHJEH3zfVP2plVu+eys0d2DlFmhoQJayFewcw==} + resolution: + { + integrity: sha512-j7+Ksi/9KfGviws6Qtf9Q7KCqRhpwrYKQPs+JBA/rKVFF/yaWLHJEH3zfVP2plVu+eys0d2DlFmhoQJayFewcw==, + } dependencies: - '@ethersproject/base64': 5.8.0 - '@ethersproject/bytes': 5.8.0 - '@ethersproject/logger': 5.8.0 - '@ethersproject/properties': 5.8.0 - '@ethersproject/strings': 5.8.0 + "@ethersproject/base64": 5.8.0 + "@ethersproject/bytes": 5.8.0 + "@ethersproject/logger": 5.8.0 + "@ethersproject/properties": 5.8.0 + "@ethersproject/strings": 5.8.0 /@ethersproject/wordlists@5.8.0: - resolution: {integrity: sha512-2df9bbXicZws2Sb5S6ET493uJ0Z84Fjr3pC4tu/qlnZERibZCeUVuqdtt+7Tv9xxhUxHoIekIA7avrKUWHrezg==} + resolution: + { + integrity: sha512-2df9bbXicZws2Sb5S6ET493uJ0Z84Fjr3pC4tu/qlnZERibZCeUVuqdtt+7Tv9xxhUxHoIekIA7avrKUWHrezg==, + } dependencies: - '@ethersproject/bytes': 5.8.0 - '@ethersproject/hash': 5.8.0 - '@ethersproject/logger': 5.8.0 - '@ethersproject/properties': 5.8.0 - '@ethersproject/strings': 5.8.0 + "@ethersproject/bytes": 5.8.0 + "@ethersproject/hash": 5.8.0 + "@ethersproject/logger": 5.8.0 + "@ethersproject/properties": 5.8.0 + "@ethersproject/strings": 5.8.0 /@humanwhocodes/momoa@2.0.4: - resolution: {integrity: sha512-RE815I4arJFtt+FVeU1Tgp9/Xvecacji8w/V6XtXsWWH/wz/eNkNbhb+ny/+PlVZjV0rxQpRSQKNKE3lcktHEA==} - engines: {node: '>=10.10.0'} + resolution: + { + integrity: sha512-RE815I4arJFtt+FVeU1Tgp9/Xvecacji8w/V6XtXsWWH/wz/eNkNbhb+ny/+PlVZjV0rxQpRSQKNKE3lcktHEA==, + } + engines: { node: ">=10.10.0" } dev: true /@layerzerolabs/lz-evm-messagelib-v2@3.0.110(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.110)(@layerzerolabs/lz-evm-v1-0.7@3.0.110)(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.4): - resolution: {integrity: sha512-I8KbvgxXkwoxcIG4ToIsdi86XycyHO/qv9MsmgrRRYl3ixnqjlFGrC4MSkDFkPEngRfMMtt3B/9lQJ6mSghA9Q==} + resolution: + { + integrity: sha512-I8KbvgxXkwoxcIG4ToIsdi86XycyHO/qv9MsmgrRRYl3ixnqjlFGrC4MSkDFkPEngRfMMtt3B/9lQJ6mSghA9Q==, + } peerDependencies: - '@arbitrum/nitro-contracts': ^1.1.0 - '@axelar-network/axelar-gmp-sdk-solidity': ^5.6.4 - '@chainlink/contracts-ccip': ^0.7.6 - '@eth-optimism/contracts': ^0.6.0 - '@layerzerolabs/lz-evm-protocol-v2': ^3.0.110 - '@layerzerolabs/lz-evm-v1-0.7': ^3.0.110 - '@openzeppelin/contracts': ^4.8.1 || ^5.0.0 - '@openzeppelin/contracts-upgradeable': ^4.8.1 || ^5.0.0 + "@arbitrum/nitro-contracts": ^1.1.0 + "@axelar-network/axelar-gmp-sdk-solidity": ^5.6.4 + "@chainlink/contracts-ccip": ^0.7.6 + "@eth-optimism/contracts": ^0.6.0 + "@layerzerolabs/lz-evm-protocol-v2": ^3.0.110 + "@layerzerolabs/lz-evm-v1-0.7": ^3.0.110 + "@openzeppelin/contracts": ^4.8.1 || ^5.0.0 + "@openzeppelin/contracts-upgradeable": ^4.8.1 || ^5.0.0 hardhat-deploy: ^0.12.4 solidity-bytes-utils: ^0.8.0 peerDependenciesMeta: - '@arbitrum/nitro-contracts': + "@arbitrum/nitro-contracts": optional: true dependencies: - '@axelar-network/axelar-gmp-sdk-solidity': 5.10.0 - '@chainlink/contracts-ccip': 0.7.6(ethers@5.8.0) - '@eth-optimism/contracts': 0.6.0(ethers@5.8.0) - '@layerzerolabs/lz-evm-protocol-v2': 3.0.110(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.4) - '@layerzerolabs/lz-evm-v1-0.7': 3.0.110(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4) - '@openzeppelin/contracts': 5.0.1 - '@openzeppelin/contracts-upgradeable': 5.0.1(@openzeppelin/contracts@5.0.1) + "@axelar-network/axelar-gmp-sdk-solidity": 5.10.0 + "@chainlink/contracts-ccip": 0.7.6(ethers@5.8.0) + "@eth-optimism/contracts": 0.6.0(ethers@5.8.0) + "@layerzerolabs/lz-evm-protocol-v2": 3.0.110(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.4) + "@layerzerolabs/lz-evm-v1-0.7": 3.0.110(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4) + "@openzeppelin/contracts": 5.0.1 + "@openzeppelin/contracts-upgradeable": 5.0.1(@openzeppelin/contracts@5.0.1) hardhat-deploy: 0.12.4 solidity-bytes-utils: 0.8.4 /@layerzerolabs/lz-evm-protocol-v2@3.0.110(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.4): - resolution: {integrity: sha512-XijBBdSippAf4KJVnpsQc8em5VuaeiDAYtsP/14JMaXRnHaTpod8cOFFLEDxczkccbQDMwqxRlKCbUXwwYn33Q==} + resolution: + { + integrity: sha512-XijBBdSippAf4KJVnpsQc8em5VuaeiDAYtsP/14JMaXRnHaTpod8cOFFLEDxczkccbQDMwqxRlKCbUXwwYn33Q==, + } peerDependencies: - '@openzeppelin/contracts': ^4.8.1 || ^5.0.0 - '@openzeppelin/contracts-upgradeable': ^4.8.1 || ^5.0.0 + "@openzeppelin/contracts": ^4.8.1 || ^5.0.0 + "@openzeppelin/contracts-upgradeable": ^4.8.1 || ^5.0.0 hardhat-deploy: ^0.12.4 solidity-bytes-utils: ^0.8.0 dependencies: - '@openzeppelin/contracts': 5.0.1 - '@openzeppelin/contracts-upgradeable': 5.0.1(@openzeppelin/contracts@5.0.1) + "@openzeppelin/contracts": 5.0.1 + "@openzeppelin/contracts-upgradeable": 5.0.1(@openzeppelin/contracts@5.0.1) hardhat-deploy: 0.12.4 solidity-bytes-utils: 0.8.4 /@layerzerolabs/lz-evm-v1-0.7@3.0.110(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4): - resolution: {integrity: sha512-Ycm0yRGLigaCbLw7/zy5O8nkDMa2Op+MgKFcFw/xA7ucKyB6ljUs0thjRjzIAXomizgETQGdFIWKLXkpNK5GcQ==} + resolution: + { + integrity: sha512-Ycm0yRGLigaCbLw7/zy5O8nkDMa2Op+MgKFcFw/xA7ucKyB6ljUs0thjRjzIAXomizgETQGdFIWKLXkpNK5GcQ==, + } peerDependencies: - '@openzeppelin/contracts': 3.4.2-solc-0.7 || ^3.4.2 || ^4.0.0 || ^5.0.0 - '@openzeppelin/contracts-upgradeable': 3.4.2-solc-0.7 || ^3.4.2 || ^4.0.0 || ^5.0.0 + "@openzeppelin/contracts": 3.4.2-solc-0.7 || ^3.4.2 || ^4.0.0 || ^5.0.0 + "@openzeppelin/contracts-upgradeable": 3.4.2-solc-0.7 || ^3.4.2 || ^4.0.0 || ^5.0.0 hardhat-deploy: ^0.12.4 dependencies: - '@openzeppelin/contracts': 5.0.1 - '@openzeppelin/contracts-upgradeable': 5.0.1(@openzeppelin/contracts@5.0.1) + "@openzeppelin/contracts": 5.0.1 + "@openzeppelin/contracts-upgradeable": 5.0.1(@openzeppelin/contracts@5.0.1) hardhat-deploy: 0.12.4 /@layerzerolabs/oapp-evm@0.3.2(@layerzerolabs/lz-evm-messagelib-v2@3.0.110)(@layerzerolabs/lz-evm-protocol-v2@3.0.110)(@layerzerolabs/lz-evm-v1-0.7@3.0.110)(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1): - resolution: {integrity: sha512-QqazLEl9KEPsipU/3m5eFDhyse+sG4bO2FWUEf/Kuee4JW6P3iIBI9wg0QfalUqLj0HL0ChFHL3yRTZVqzxrww==} + resolution: + { + integrity: sha512-QqazLEl9KEPsipU/3m5eFDhyse+sG4bO2FWUEf/Kuee4JW6P3iIBI9wg0QfalUqLj0HL0ChFHL3yRTZVqzxrww==, + } peerDependencies: - '@layerzerolabs/lz-evm-messagelib-v2': ^3.0.75 - '@layerzerolabs/lz-evm-protocol-v2': ^3.0.75 - '@layerzerolabs/lz-evm-v1-0.7': ^3.0.75 - '@openzeppelin/contracts': ^4.8.1 || ^5.0.0 - '@openzeppelin/contracts-upgradeable': ^4.8.1 || ^5.0.0 - dependencies: - '@layerzerolabs/lz-evm-messagelib-v2': 3.0.110(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.110)(@layerzerolabs/lz-evm-v1-0.7@3.0.110)(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.4) - '@layerzerolabs/lz-evm-protocol-v2': 3.0.110(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.4) - '@layerzerolabs/lz-evm-v1-0.7': 3.0.110(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4) - '@openzeppelin/contracts': 5.0.1 - '@openzeppelin/contracts-upgradeable': 5.0.1(@openzeppelin/contracts@5.0.1) + "@layerzerolabs/lz-evm-messagelib-v2": ^3.0.75 + "@layerzerolabs/lz-evm-protocol-v2": ^3.0.75 + "@layerzerolabs/lz-evm-v1-0.7": ^3.0.75 + "@openzeppelin/contracts": ^4.8.1 || ^5.0.0 + "@openzeppelin/contracts-upgradeable": ^4.8.1 || ^5.0.0 + dependencies: + "@layerzerolabs/lz-evm-messagelib-v2": 3.0.110(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.110)(@layerzerolabs/lz-evm-v1-0.7@3.0.110)(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.4) + "@layerzerolabs/lz-evm-protocol-v2": 3.0.110(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.4) + "@layerzerolabs/lz-evm-v1-0.7": 3.0.110(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4) + "@openzeppelin/contracts": 5.0.1 + "@openzeppelin/contracts-upgradeable": 5.0.1(@openzeppelin/contracts@5.0.1) ethers: 5.8.0 transitivePeerDependencies: - bufferutil - utf-8-validate /@layerzerolabs/oft-evm@3.1.4(@layerzerolabs/lz-evm-messagelib-v2@3.0.110)(@layerzerolabs/lz-evm-protocol-v2@3.0.110)(@layerzerolabs/lz-evm-v1-0.7@3.0.110)(@layerzerolabs/oapp-evm@0.3.2)(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1): - resolution: {integrity: sha512-jxuEXtzAv2x/ZErBtg6OI6rxq4KyMamPgy8+r3/AQ5uD4Ih2Sd51mBIebpzueJKqMk7MNdOauLfYRRK6tOFWXQ==} + resolution: + { + integrity: sha512-jxuEXtzAv2x/ZErBtg6OI6rxq4KyMamPgy8+r3/AQ5uD4Ih2Sd51mBIebpzueJKqMk7MNdOauLfYRRK6tOFWXQ==, + } peerDependencies: - '@layerzerolabs/lz-evm-messagelib-v2': ^3.0.75 - '@layerzerolabs/lz-evm-protocol-v2': ^3.0.75 - '@layerzerolabs/lz-evm-v1-0.7': ^3.0.75 - '@layerzerolabs/oapp-evm': ^0.3.2 - '@openzeppelin/contracts': ^4.8.1 || ^5.0.0 - '@openzeppelin/contracts-upgradeable': ^4.8.1 || ^5.0.0 - dependencies: - '@layerzerolabs/lz-evm-messagelib-v2': 3.0.110(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.110)(@layerzerolabs/lz-evm-v1-0.7@3.0.110)(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.4) - '@layerzerolabs/lz-evm-protocol-v2': 3.0.110(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.4) - '@layerzerolabs/lz-evm-v1-0.7': 3.0.110(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4) - '@layerzerolabs/oapp-evm': 0.3.2(@layerzerolabs/lz-evm-messagelib-v2@3.0.110)(@layerzerolabs/lz-evm-protocol-v2@3.0.110)(@layerzerolabs/lz-evm-v1-0.7@3.0.110)(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1) - '@openzeppelin/contracts': 5.0.1 - '@openzeppelin/contracts-upgradeable': 5.0.1(@openzeppelin/contracts@5.0.1) + "@layerzerolabs/lz-evm-messagelib-v2": ^3.0.75 + "@layerzerolabs/lz-evm-protocol-v2": ^3.0.75 + "@layerzerolabs/lz-evm-v1-0.7": ^3.0.75 + "@layerzerolabs/oapp-evm": ^0.3.2 + "@openzeppelin/contracts": ^4.8.1 || ^5.0.0 + "@openzeppelin/contracts-upgradeable": ^4.8.1 || ^5.0.0 + dependencies: + "@layerzerolabs/lz-evm-messagelib-v2": 3.0.110(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.110)(@layerzerolabs/lz-evm-v1-0.7@3.0.110)(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.4) + "@layerzerolabs/lz-evm-protocol-v2": 3.0.110(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.4) + "@layerzerolabs/lz-evm-v1-0.7": 3.0.110(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4) + "@layerzerolabs/oapp-evm": 0.3.2(@layerzerolabs/lz-evm-messagelib-v2@3.0.110)(@layerzerolabs/lz-evm-protocol-v2@3.0.110)(@layerzerolabs/lz-evm-v1-0.7@3.0.110)(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1) + "@openzeppelin/contracts": 5.0.1 + "@openzeppelin/contracts-upgradeable": 5.0.1(@openzeppelin/contracts@5.0.1) /@layerzerolabs/test-devtools-evm-foundry@6.0.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.110)(@layerzerolabs/lz-evm-protocol-v2@3.0.110)(@layerzerolabs/lz-evm-v1-0.7@3.0.110)(@layerzerolabs/oapp-evm@0.3.2)(@layerzerolabs/oft-evm@3.1.4)(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1): - resolution: {integrity: sha512-yJQzxcW2mVwnSB4vGmUfxDbR0K72f3jf+An6swmTXXrMvtZ5v9mKOUhN40c3mmrUq+/FJtvg+5sJCll37r369A==} + resolution: + { + integrity: sha512-yJQzxcW2mVwnSB4vGmUfxDbR0K72f3jf+An6swmTXXrMvtZ5v9mKOUhN40c3mmrUq+/FJtvg+5sJCll37r369A==, + } peerDependencies: - '@layerzerolabs/lz-evm-messagelib-v2': ^3.0.75 - '@layerzerolabs/lz-evm-protocol-v2': ^3.0.75 - '@layerzerolabs/lz-evm-v1-0.7': ^3.0.75 - '@layerzerolabs/oapp-evm': ^0.3.2 - '@layerzerolabs/oft-evm': ^3.1.3 - '@openzeppelin/contracts': ^4.9.5 || ^5.0.0 - '@openzeppelin/contracts-upgradeable': ^4.9.5 || ^5.0.0 - dependencies: - '@layerzerolabs/lz-evm-messagelib-v2': 3.0.110(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.110)(@layerzerolabs/lz-evm-v1-0.7@3.0.110)(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.4) - '@layerzerolabs/lz-evm-protocol-v2': 3.0.110(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.4) - '@layerzerolabs/lz-evm-v1-0.7': 3.0.110(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4) - '@layerzerolabs/oapp-evm': 0.3.2(@layerzerolabs/lz-evm-messagelib-v2@3.0.110)(@layerzerolabs/lz-evm-protocol-v2@3.0.110)(@layerzerolabs/lz-evm-v1-0.7@3.0.110)(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1) - '@layerzerolabs/oft-evm': 3.1.4(@layerzerolabs/lz-evm-messagelib-v2@3.0.110)(@layerzerolabs/lz-evm-protocol-v2@3.0.110)(@layerzerolabs/lz-evm-v1-0.7@3.0.110)(@layerzerolabs/oapp-evm@0.3.2)(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1) - '@openzeppelin/contracts': 5.0.1 - '@openzeppelin/contracts-upgradeable': 5.0.1(@openzeppelin/contracts@5.0.1) + "@layerzerolabs/lz-evm-messagelib-v2": ^3.0.75 + "@layerzerolabs/lz-evm-protocol-v2": ^3.0.75 + "@layerzerolabs/lz-evm-v1-0.7": ^3.0.75 + "@layerzerolabs/oapp-evm": ^0.3.2 + "@layerzerolabs/oft-evm": ^3.1.3 + "@openzeppelin/contracts": ^4.9.5 || ^5.0.0 + "@openzeppelin/contracts-upgradeable": ^4.9.5 || ^5.0.0 + dependencies: + "@layerzerolabs/lz-evm-messagelib-v2": 3.0.110(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.110)(@layerzerolabs/lz-evm-v1-0.7@3.0.110)(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.4) + "@layerzerolabs/lz-evm-protocol-v2": 3.0.110(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.4) + "@layerzerolabs/lz-evm-v1-0.7": 3.0.110(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1)(hardhat-deploy@0.12.4) + "@layerzerolabs/oapp-evm": 0.3.2(@layerzerolabs/lz-evm-messagelib-v2@3.0.110)(@layerzerolabs/lz-evm-protocol-v2@3.0.110)(@layerzerolabs/lz-evm-v1-0.7@3.0.110)(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1) + "@layerzerolabs/oft-evm": 3.1.4(@layerzerolabs/lz-evm-messagelib-v2@3.0.110)(@layerzerolabs/lz-evm-protocol-v2@3.0.110)(@layerzerolabs/lz-evm-v1-0.7@3.0.110)(@layerzerolabs/oapp-evm@0.3.2)(@openzeppelin/contracts-upgradeable@5.0.1)(@openzeppelin/contracts@5.0.1) + "@openzeppelin/contracts": 5.0.1 + "@openzeppelin/contracts-upgradeable": 5.0.1(@openzeppelin/contracts@5.0.1) dev: true /@oozcitak/dom@1.15.10: - resolution: {integrity: sha512-0JT29/LaxVgRcGKvHmSrUTEvZ8BXvZhGl2LASRUgHqDTC1M5g1pLmVv56IYNyt3bG2CUjDkc67wnyZC14pbQrQ==} - engines: {node: '>=8.0'} + resolution: + { + integrity: sha512-0JT29/LaxVgRcGKvHmSrUTEvZ8BXvZhGl2LASRUgHqDTC1M5g1pLmVv56IYNyt3bG2CUjDkc67wnyZC14pbQrQ==, + } + engines: { node: ">=8.0" } dependencies: - '@oozcitak/infra': 1.0.8 - '@oozcitak/url': 1.0.4 - '@oozcitak/util': 8.3.8 + "@oozcitak/infra": 1.0.8 + "@oozcitak/url": 1.0.4 + "@oozcitak/util": 8.3.8 dev: true /@oozcitak/infra@1.0.8: - resolution: {integrity: sha512-JRAUc9VR6IGHOL7OGF+yrvs0LO8SlqGnPAMqyzOuFZPSZSXI7Xf2O9+awQPSMXgIWGtgUf/dA6Hs6X6ySEaWTg==} - engines: {node: '>=6.0'} + resolution: + { + integrity: sha512-JRAUc9VR6IGHOL7OGF+yrvs0LO8SlqGnPAMqyzOuFZPSZSXI7Xf2O9+awQPSMXgIWGtgUf/dA6Hs6X6ySEaWTg==, + } + engines: { node: ">=6.0" } dependencies: - '@oozcitak/util': 8.3.8 + "@oozcitak/util": 8.3.8 dev: true /@oozcitak/url@1.0.4: - resolution: {integrity: sha512-kDcD8y+y3FCSOvnBI6HJgl00viO/nGbQoCINmQ0h98OhnGITrWR3bOGfwYCthgcrV8AnTJz8MzslTQbC3SOAmw==} - engines: {node: '>=8.0'} + resolution: + { + integrity: sha512-kDcD8y+y3FCSOvnBI6HJgl00viO/nGbQoCINmQ0h98OhnGITrWR3bOGfwYCthgcrV8AnTJz8MzslTQbC3SOAmw==, + } + engines: { node: ">=8.0" } dependencies: - '@oozcitak/infra': 1.0.8 - '@oozcitak/util': 8.3.8 + "@oozcitak/infra": 1.0.8 + "@oozcitak/util": 8.3.8 dev: true /@oozcitak/util@8.3.8: - resolution: {integrity: sha512-T8TbSnGsxo6TDBJx/Sgv/BlVJL3tshxZP7Aq5R1mSnM5OcHY2dQaxLMu2+E8u3gN0MLOzdjurqN4ZRVuzQycOQ==} - engines: {node: '>=8.0'} + resolution: + { + integrity: sha512-T8TbSnGsxo6TDBJx/Sgv/BlVJL3tshxZP7Aq5R1mSnM5OcHY2dQaxLMu2+E8u3gN0MLOzdjurqN4ZRVuzQycOQ==, + } + engines: { node: ">=8.0" } dev: true /@openzeppelin/contracts-upgradeable@4.7.3: - resolution: {integrity: sha512-+wuegAMaLcZnLCJIvrVUDzA9z/Wp93f0Dla/4jJvIhijRrPabjQbZe6fWiECLaJyfn5ci9fqf9vTw3xpQOad2A==} + resolution: + { + integrity: sha512-+wuegAMaLcZnLCJIvrVUDzA9z/Wp93f0Dla/4jJvIhijRrPabjQbZe6fWiECLaJyfn5ci9fqf9vTw3xpQOad2A==, + } /@openzeppelin/contracts-upgradeable@5.0.1(@openzeppelin/contracts@5.0.1): - resolution: {integrity: sha512-MvaLoPnVcoZr/qqZP+4cl9piuR4gg0iIGgxVSZ/AL1iId3M6IdEHzz9Naw5Lirl4KKBI6ciTVnX07yL4dOMIJg==} + resolution: + { + integrity: sha512-MvaLoPnVcoZr/qqZP+4cl9piuR4gg0iIGgxVSZ/AL1iId3M6IdEHzz9Naw5Lirl4KKBI6ciTVnX07yL4dOMIJg==, + } peerDependencies: - '@openzeppelin/contracts': 5.0.1 + "@openzeppelin/contracts": 5.0.1 dependencies: - '@openzeppelin/contracts': 5.0.1 + "@openzeppelin/contracts": 5.0.1 /@openzeppelin/contracts@3.4.2: - resolution: {integrity: sha512-z0zMCjyhhp4y7XKAcDAi3Vgms4T2PstwBdahiO0+9NaGICQKjynK3wduSRplTgk4LXmoO1yfDGO5RbjKYxtuxA==} + resolution: + { + integrity: sha512-z0zMCjyhhp4y7XKAcDAi3Vgms4T2PstwBdahiO0+9NaGICQKjynK3wduSRplTgk4LXmoO1yfDGO5RbjKYxtuxA==, + } /@openzeppelin/contracts@4.3.3: - resolution: {integrity: sha512-tDBopO1c98Yk7Cv/PZlHqrvtVjlgK5R4J6jxLwoO7qxK4xqOiZG+zSkIvGFpPZ0ikc3QOED3plgdqjgNTnBc7g==} + resolution: + { + integrity: sha512-tDBopO1c98Yk7Cv/PZlHqrvtVjlgK5R4J6jxLwoO7qxK4xqOiZG+zSkIvGFpPZ0ikc3QOED3plgdqjgNTnBc7g==, + } /@openzeppelin/contracts@4.9.6: - resolution: {integrity: sha512-xSmezSupL+y9VkHZJGDoCBpmnB2ogM13ccaYDWqJTfS3dbuHkgjuwDFUmaFauBCboQMGB/S5UqUl2y54X99BmA==} + resolution: + { + integrity: sha512-xSmezSupL+y9VkHZJGDoCBpmnB2ogM13ccaYDWqJTfS3dbuHkgjuwDFUmaFauBCboQMGB/S5UqUl2y54X99BmA==, + } dev: true /@openzeppelin/contracts@5.0.1: - resolution: {integrity: sha512-yQJaT5HDp9hYOOp4jTYxMsR02gdFZFXhewX5HW9Jo4fsqSVqqyIO/xTHdWDaKX5a3pv1txmf076Lziz+sO7L1w==} + resolution: + { + integrity: sha512-yQJaT5HDp9hYOOp4jTYxMsR02gdFZFXhewX5HW9Jo4fsqSVqqyIO/xTHdWDaKX5a3pv1txmf076Lziz+sO7L1w==, + } /@pnpm/config.env-replace@1.1.0: - resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} - engines: {node: '>=12.22.0'} + resolution: + { + integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==, + } + engines: { node: ">=12.22.0" } dev: true /@pnpm/network.ca-file@1.0.2: - resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} - engines: {node: '>=12.22.0'} + resolution: + { + integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==, + } + engines: { node: ">=12.22.0" } dependencies: graceful-fs: 4.2.10 dev: true /@pnpm/npm-conf@2.3.1: - resolution: {integrity: sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==} - engines: {node: '>=12'} - dependencies: - '@pnpm/config.env-replace': 1.1.0 - '@pnpm/network.ca-file': 1.0.2 + resolution: + { + integrity: sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==, + } + engines: { node: ">=12" } + dependencies: + "@pnpm/config.env-replace": 1.1.0 + "@pnpm/network.ca-file": 1.0.2 config-chain: 1.1.13 dev: true /@prb/test@0.6.4: - resolution: {integrity: sha512-P0tTMsB6XQ0Wp61EYdXJYFhsOVGyZvcOFub2y9yk0sF+GYDusctR7DzEI+vOP0SILm3knFkEJASjewHEBppdRQ==} + resolution: + { + integrity: sha512-P0tTMsB6XQ0Wp61EYdXJYFhsOVGyZvcOFub2y9yk0sF+GYDusctR7DzEI+vOP0SILm3knFkEJASjewHEBppdRQ==, + } dev: true /@sindresorhus/is@5.6.0: - resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==} - engines: {node: '>=14.16'} + resolution: + { + integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==, + } + engines: { node: ">=14.16" } dev: true /@solidity-parser/parser@0.20.1: - resolution: {integrity: sha512-58I2sRpzaQUN+jJmWbHfbWf9AKfzqCI8JAdFB0vbyY+u8tBRcuTt9LxzasvR0LGQpcRv97eyV7l61FQ3Ib7zVw==} + resolution: + { + integrity: sha512-58I2sRpzaQUN+jJmWbHfbWf9AKfzqCI8JAdFB0vbyY+u8tBRcuTt9LxzasvR0LGQpcRv97eyV7l61FQ3Ib7zVw==, + } dev: true /@szmarczak/http-timer@5.0.1: - resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} - engines: {node: '>=14.16'} + resolution: + { + integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==, + } + engines: { node: ">=14.16" } dependencies: defer-to-connect: 2.0.1 dev: true /@tootallnate/quickjs-emscripten@0.23.0: - resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} + resolution: + { + integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==, + } dev: true /@types/http-cache-semantics@4.0.4: - resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} + resolution: + { + integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==, + } dev: true /@types/qs@6.14.0: - resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==} + resolution: + { + integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==, + } /aes-js@3.0.0: - resolution: {integrity: sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==} + resolution: + { + integrity: sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==, + } /agent-base@7.1.4: - resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} - engines: {node: '>= 14'} + resolution: + { + integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==, + } + engines: { node: ">= 14" } dev: true /ajv-errors@1.0.1(ajv@6.12.6): - resolution: {integrity: sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==} + resolution: + { + integrity: sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==, + } peerDependencies: - ajv: '>=5.0.0' + ajv: ">=5.0.0" dependencies: ajv: 6.12.6 dev: true /ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + resolution: + { + integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==, + } dependencies: fast-deep-equal: 3.1.3 fast-json-stable-stringify: 2.1.0 @@ -670,7 +870,10 @@ packages: dev: true /ajv@8.17.1: - resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + resolution: + { + integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==, + } dependencies: fast-deep-equal: 3.1.3 fast-uri: 3.0.6 @@ -679,94 +882,148 @@ packages: dev: true /ansi-colors@4.1.3: - resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==, + } + engines: { node: ">=6" } /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==, + } + engines: { node: ">=8" } /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==, + } + engines: { node: ">=8" } dependencies: color-convert: 2.0.1 /antlr4@4.13.2: - resolution: {integrity: sha512-QiVbZhyy4xAZ17UPEuG3YTOt8ZaoeOR1CvEAqrEsDBsOqINslaB147i9xqljZqoyf5S+EUlGStaj+t22LT9MOg==} - engines: {node: '>=16'} + resolution: + { + integrity: sha512-QiVbZhyy4xAZ17UPEuG3YTOt8ZaoeOR1CvEAqrEsDBsOqINslaB147i9xqljZqoyf5S+EUlGStaj+t22LT9MOg==, + } + engines: { node: ">=16" } dev: true /anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} + resolution: + { + integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==, + } + engines: { node: ">= 8" } dependencies: normalize-path: 3.0.0 picomatch: 2.3.1 /argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + resolution: + { + integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==, + } dependencies: sprintf-js: 1.0.3 dev: true /argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + resolution: + { + integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==, + } dev: true /assertion-error@1.1.0: - resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + resolution: + { + integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==, + } /ast-parents@0.0.1: - resolution: {integrity: sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==} + resolution: + { + integrity: sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==, + } dev: true /ast-types@0.13.4: - resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==, + } + engines: { node: ">=4" } dependencies: tslib: 2.8.1 dev: true /astral-regex@2.0.0: - resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==, + } + engines: { node: ">=8" } dev: true /async@3.2.6: - resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + resolution: + { + integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==, + } dev: true /asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + resolution: + { + integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==, + } /axios@0.21.4(debug@4.4.1): - resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} + resolution: + { + integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==, + } dependencies: follow-redirects: 1.15.9(debug@4.4.1) transitivePeerDependencies: - debug /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + resolution: + { + integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==, + } dev: true /basic-ftp@5.0.5: - resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==} - engines: {node: '>=10.0.0'} + resolution: + { + integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==, + } + engines: { node: ">=10.0.0" } dev: true /bech32@1.1.4: - resolution: {integrity: sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==} + resolution: + { + integrity: sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==, + } /better-ajv-errors@2.0.2(ajv@6.12.6): - resolution: {integrity: sha512-1cLrJXEq46n0hjV8dDYwg9LKYjDb3KbeW7nZTv4kvfoDD9c2DXHIE31nxM+Y/cIfXMggLUfmxbm6h/JoM/yotA==} - engines: {node: '>= 18.20.6'} + resolution: + { + integrity: sha512-1cLrJXEq46n0hjV8dDYwg9LKYjDb3KbeW7nZTv4kvfoDD9c2DXHIE31nxM+Y/cIfXMggLUfmxbm6h/JoM/yotA==, + } + engines: { node: ">= 18.20.6" } peerDependencies: ajv: 4.11.8 - 8 dependencies: - '@babel/code-frame': 7.27.1 - '@humanwhocodes/momoa': 2.0.4 + "@babel/code-frame": 7.27.1 + "@humanwhocodes/momoa": 2.0.4 ajv: 6.12.6 chalk: 4.1.2 jsonpointer: 5.0.1 @@ -774,48 +1031,78 @@ packages: dev: true /binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==, + } + engines: { node: ">=8" } /bn.js@4.12.2: - resolution: {integrity: sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==} + resolution: + { + integrity: sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==, + } /bn.js@5.2.2: - resolution: {integrity: sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==} + resolution: + { + integrity: sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==, + } /boolbase@1.0.0: - resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + resolution: + { + integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==, + } dev: true /brace-expansion@2.0.2: - resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + resolution: + { + integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==, + } dependencies: balanced-match: 1.0.2 dev: true /braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==, + } + engines: { node: ">=8" } dependencies: fill-range: 7.1.1 /brorand@1.1.0: - resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + resolution: + { + integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==, + } /bufio@1.2.3: - resolution: {integrity: sha512-5Tt66bRzYUSlVZatc0E92uDenreJ+DpTBmSAUwL4VSxJn3e6cUyYwx+PoqML0GRZatgA/VX8ybhxItF8InZgqA==} - engines: {node: '>=8.0.0'} + resolution: + { + integrity: sha512-5Tt66bRzYUSlVZatc0E92uDenreJ+DpTBmSAUwL4VSxJn3e6cUyYwx+PoqML0GRZatgA/VX8ybhxItF8InZgqA==, + } + engines: { node: ">=8.0.0" } /cacheable-lookup@7.0.0: - resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==} - engines: {node: '>=14.16'} + resolution: + { + integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==, + } + engines: { node: ">=14.16" } dev: true /cacheable-request@10.2.14: - resolution: {integrity: sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==} - engines: {node: '>=14.16'} + resolution: + { + integrity: sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==, + } + engines: { node: ">=14.16" } dependencies: - '@types/http-cache-semantics': 4.0.4 + "@types/http-cache-semantics": 4.0.4 get-stream: 6.0.1 http-cache-semantics: 4.2.0 keyv: 4.5.4 @@ -825,27 +1112,39 @@ packages: dev: true /call-bind-apply-helpers@1.0.2: - resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==, + } + engines: { node: ">= 0.4" } dependencies: es-errors: 1.3.0 function-bind: 1.1.2 /call-bound@1.0.4: - resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==, + } + engines: { node: ">= 0.4" } dependencies: call-bind-apply-helpers: 1.0.2 get-intrinsic: 1.3.0 /callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==, + } + engines: { node: ">=6" } dev: true /chai@4.5.0: - resolution: {integrity: sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==, + } + engines: { node: ">=4" } dependencies: assertion-error: 1.1.0 check-error: 1.0.3 @@ -856,24 +1155,36 @@ packages: type-detect: 4.1.0 /chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==, + } + engines: { node: ">=10" } dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 /chalk@5.4.1: - resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + resolution: + { + integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==, + } + engines: { node: ^12.17.0 || ^14.13 || >=16.0.0 } dev: true /check-error@1.0.3: - resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} + resolution: + { + integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==, + } dependencies: get-func-name: 2.0.2 /cheerio-select@2.1.0: - resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} + resolution: + { + integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==, + } dependencies: boolbase: 1.0.0 css-select: 5.2.2 @@ -884,8 +1195,11 @@ packages: dev: true /cheerio@1.1.0: - resolution: {integrity: sha512-+0hMx9eYhJvWbgpKV9hN7jg0JcwydpopZE4hgi+KvQtByZXPp04NiCWU0LzcAbP63abZckIHkTQaXVF52mX3xQ==} - engines: {node: '>=18.17'} + resolution: + { + integrity: sha512-+0hMx9eYhJvWbgpKV9hN7jg0JcwydpopZE4hgi+KvQtByZXPp04NiCWU0LzcAbP63abZckIHkTQaXVF52mX3xQ==, + } + engines: { node: ">=18.17" } dependencies: cheerio-select: 2.1.0 dom-serializer: 2.0.0 @@ -901,8 +1215,11 @@ packages: dev: true /chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} + resolution: + { + integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==, + } + engines: { node: ">= 8.10.0" } dependencies: anymatch: 3.1.3 braces: 3.0.3 @@ -915,42 +1232,63 @@ packages: fsevents: 2.3.3 /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} + resolution: + { + integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==, + } + engines: { node: ">=7.0.0" } dependencies: color-name: 1.1.4 /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + resolution: + { + integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==, + } /combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} + resolution: + { + integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==, + } + engines: { node: ">= 0.8" } dependencies: delayed-stream: 1.0.0 /commander@10.0.1: - resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} - engines: {node: '>=14'} + resolution: + { + integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==, + } + engines: { node: ">=14" } dev: true /commander@13.1.0: - resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==, + } + engines: { node: ">=18" } dev: true /config-chain@1.1.13: - resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + resolution: + { + integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==, + } dependencies: ini: 1.3.8 proto-list: 1.2.4 dev: true /cosmiconfig@8.3.6: - resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} - engines: {node: '>=14'} + resolution: + { + integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==, + } + engines: { node: ">=14" } peerDependencies: - typescript: '>=4.9.5' + typescript: ">=4.9.5" peerDependenciesMeta: typescript: optional: true @@ -962,7 +1300,10 @@ packages: dev: true /css-select@5.2.2: - resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} + resolution: + { + integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==, + } dependencies: boolbase: 1.0.0 css-what: 6.2.2 @@ -972,20 +1313,29 @@ packages: dev: true /css-what@6.2.2: - resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} - engines: {node: '>= 6'} + resolution: + { + integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==, + } + engines: { node: ">= 6" } dev: true /data-uri-to-buffer@6.0.2: - resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} - engines: {node: '>= 14'} + resolution: + { + integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==, + } + engines: { node: ">= 14" } dev: true /debug@4.4.1: - resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} - engines: {node: '>=6.0'} + resolution: + { + integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==, + } + engines: { node: ">=6.0" } peerDependencies: - supports-color: '*' + supports-color: "*" peerDependenciesMeta: supports-color: optional: true @@ -993,31 +1343,46 @@ packages: ms: 2.1.3 /decompress-response@6.0.0: - resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==, + } + engines: { node: ">=10" } dependencies: mimic-response: 3.1.0 dev: true /deep-eql@4.1.4: - resolution: {integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==, + } + engines: { node: ">=6" } dependencies: type-detect: 4.1.0 /deep-extend@0.6.0: - resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} - engines: {node: '>=4.0.0'} + resolution: + { + integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==, + } + engines: { node: ">=4.0.0" } dev: true /defer-to-connect@2.0.1: - resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==, + } + engines: { node: ">=10" } dev: true /degenerator@5.0.1: - resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} - engines: {node: '>= 14'} + resolution: + { + integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==, + } + engines: { node: ">= 14" } dependencies: ast-types: 0.13.4 escodegen: 2.1.0 @@ -1025,11 +1390,17 @@ packages: dev: true /delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} + resolution: + { + integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==, + } + engines: { node: ">=0.4.0" } /dom-serializer@2.0.0: - resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + resolution: + { + integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==, + } dependencies: domelementtype: 2.3.0 domhandler: 5.0.3 @@ -1037,18 +1408,27 @@ packages: dev: true /domelementtype@2.3.0: - resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + resolution: + { + integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==, + } dev: true /domhandler@5.0.3: - resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} - engines: {node: '>= 4'} + resolution: + { + integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==, + } + engines: { node: ">= 4" } dependencies: domelementtype: 2.3.0 dev: true /domutils@3.2.2: - resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + resolution: + { + integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==, + } dependencies: dom-serializer: 2.0.0 domelementtype: 2.3.0 @@ -1056,15 +1436,21 @@ packages: dev: true /dunder-proto@1.0.1: - resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==, + } + engines: { node: ">= 0.4" } dependencies: call-bind-apply-helpers: 1.0.2 es-errors: 1.3.0 gopd: 1.2.0 /elliptic@6.6.1: - resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} + resolution: + { + integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==, + } dependencies: bn.js: 4.12.2 brorand: 1.1.0 @@ -1075,59 +1461,92 @@ packages: minimalistic-crypto-utils: 1.0.1 /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + resolution: + { + integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==, + } dev: true /encode-utf8@1.0.3: - resolution: {integrity: sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==} + resolution: + { + integrity: sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==, + } /encoding-sniffer@0.2.1: - resolution: {integrity: sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==} + resolution: + { + integrity: sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==, + } dependencies: iconv-lite: 0.6.3 whatwg-encoding: 3.1.1 dev: true /enquirer@2.4.1: - resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} - engines: {node: '>=8.6'} + resolution: + { + integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==, + } + engines: { node: ">=8.6" } dependencies: ansi-colors: 4.1.3 strip-ansi: 6.0.1 /entities@4.5.0: - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} - engines: {node: '>=0.12'} + resolution: + { + integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==, + } + engines: { node: ">=0.12" } dev: true /entities@6.0.1: - resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} - engines: {node: '>=0.12'} + resolution: + { + integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==, + } + engines: { node: ">=0.12" } dev: true /error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + resolution: + { + integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==, + } dependencies: is-arrayish: 0.2.1 dev: true /es-define-property@1.0.1: - resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==, + } + engines: { node: ">= 0.4" } /es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==, + } + engines: { node: ">= 0.4" } /es-object-atoms@1.1.1: - resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==, + } + engines: { node: ">= 0.4" } dependencies: es-errors: 1.3.0 /es-set-tostringtag@2.1.0: - resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==, + } + engines: { node: ">= 0.4" } dependencies: es-errors: 1.3.0 get-intrinsic: 1.3.0 @@ -1135,8 +1554,11 @@ packages: hasown: 2.0.2 /escodegen@2.1.0: - resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} - engines: {node: '>=6.0'} + resolution: + { + integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==, + } + engines: { node: ">=6.0" } hasBin: true dependencies: esprima: 4.0.1 @@ -1147,90 +1569,123 @@ packages: dev: true /esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==, + } + engines: { node: ">=4" } hasBin: true dev: true /estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} + resolution: + { + integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==, + } + engines: { node: ">=4.0" } dev: true /esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==, + } + engines: { node: ">=0.10.0" } dev: true /ethers@5.8.0: - resolution: {integrity: sha512-DUq+7fHrCg1aPDFCHx6UIPb3nmt2XMpM7Y/g2gLhsl3lIBqeAfOJIl1qEvRf2uq3BiKxmh6Fh5pfp2ieyek7Kg==} - dependencies: - '@ethersproject/abi': 5.8.0 - '@ethersproject/abstract-provider': 5.8.0 - '@ethersproject/abstract-signer': 5.8.0 - '@ethersproject/address': 5.8.0 - '@ethersproject/base64': 5.8.0 - '@ethersproject/basex': 5.8.0 - '@ethersproject/bignumber': 5.8.0 - '@ethersproject/bytes': 5.8.0 - '@ethersproject/constants': 5.8.0 - '@ethersproject/contracts': 5.8.0 - '@ethersproject/hash': 5.8.0 - '@ethersproject/hdnode': 5.8.0 - '@ethersproject/json-wallets': 5.8.0 - '@ethersproject/keccak256': 5.8.0 - '@ethersproject/logger': 5.8.0 - '@ethersproject/networks': 5.8.0 - '@ethersproject/pbkdf2': 5.8.0 - '@ethersproject/properties': 5.8.0 - '@ethersproject/providers': 5.8.0 - '@ethersproject/random': 5.8.0 - '@ethersproject/rlp': 5.8.0 - '@ethersproject/sha2': 5.8.0 - '@ethersproject/signing-key': 5.8.0 - '@ethersproject/solidity': 5.8.0 - '@ethersproject/strings': 5.8.0 - '@ethersproject/transactions': 5.8.0 - '@ethersproject/units': 5.8.0 - '@ethersproject/wallet': 5.8.0 - '@ethersproject/web': 5.8.0 - '@ethersproject/wordlists': 5.8.0 + resolution: + { + integrity: sha512-DUq+7fHrCg1aPDFCHx6UIPb3nmt2XMpM7Y/g2gLhsl3lIBqeAfOJIl1qEvRf2uq3BiKxmh6Fh5pfp2ieyek7Kg==, + } + dependencies: + "@ethersproject/abi": 5.8.0 + "@ethersproject/abstract-provider": 5.8.0 + "@ethersproject/abstract-signer": 5.8.0 + "@ethersproject/address": 5.8.0 + "@ethersproject/base64": 5.8.0 + "@ethersproject/basex": 5.8.0 + "@ethersproject/bignumber": 5.8.0 + "@ethersproject/bytes": 5.8.0 + "@ethersproject/constants": 5.8.0 + "@ethersproject/contracts": 5.8.0 + "@ethersproject/hash": 5.8.0 + "@ethersproject/hdnode": 5.8.0 + "@ethersproject/json-wallets": 5.8.0 + "@ethersproject/keccak256": 5.8.0 + "@ethersproject/logger": 5.8.0 + "@ethersproject/networks": 5.8.0 + "@ethersproject/pbkdf2": 5.8.0 + "@ethersproject/properties": 5.8.0 + "@ethersproject/providers": 5.8.0 + "@ethersproject/random": 5.8.0 + "@ethersproject/rlp": 5.8.0 + "@ethersproject/sha2": 5.8.0 + "@ethersproject/signing-key": 5.8.0 + "@ethersproject/solidity": 5.8.0 + "@ethersproject/strings": 5.8.0 + "@ethersproject/transactions": 5.8.0 + "@ethersproject/units": 5.8.0 + "@ethersproject/wallet": 5.8.0 + "@ethersproject/web": 5.8.0 + "@ethersproject/wordlists": 5.8.0 transitivePeerDependencies: - bufferutil - utf-8-validate /fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + resolution: + { + integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==, + } dev: true /fast-diff@1.3.0: - resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + resolution: + { + integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==, + } dev: true /fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + resolution: + { + integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==, + } dev: true /fast-uri@3.0.6: - resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==} + resolution: + { + integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==, + } dev: true /fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==, + } + engines: { node: ">=8" } dependencies: to-regex-range: 5.0.1 /fmix@0.1.0: - resolution: {integrity: sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w==} + resolution: + { + integrity: sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w==, + } dependencies: imul: 1.0.1 /follow-redirects@1.15.9(debug@4.4.1): - resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} - engines: {node: '>=4.0'} + resolution: + { + integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==, + } + engines: { node: ">=4.0" } peerDependencies: - debug: '*' + debug: "*" peerDependenciesMeta: debug: optional: true @@ -1238,13 +1693,19 @@ packages: debug: 4.4.1 /form-data-encoder@2.1.4: - resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} - engines: {node: '>= 14.17'} + resolution: + { + integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==, + } + engines: { node: ">= 14.17" } dev: true /form-data@4.0.3: - resolution: {integrity: sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==} - engines: {node: '>= 6'} + resolution: + { + integrity: sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==, + } + engines: { node: ">= 6" } dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 @@ -1253,16 +1714,22 @@ packages: mime-types: 2.1.35 /fs-extra@10.1.0: - resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==, + } + engines: { node: ">=12" } dependencies: graceful-fs: 4.2.11 jsonfile: 6.1.0 universalify: 2.0.1 /fs-extra@11.3.0: - resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==} - engines: {node: '>=14.14'} + resolution: + { + integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==, + } + engines: { node: ">=14.14" } dependencies: graceful-fs: 4.2.11 jsonfile: 6.1.0 @@ -1270,25 +1737,40 @@ packages: dev: true /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + resolution: + { + integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==, + } dev: true /fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + resolution: + { + integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==, + } + engines: { node: ^8.16.0 || ^10.6.0 || >=11.0.0 } os: [darwin] requiresBuild: true optional: true /function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + resolution: + { + integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==, + } /get-func-name@2.0.2: - resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} + resolution: + { + integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==, + } /get-intrinsic@1.3.0: - resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==, + } + engines: { node: ">= 0.4" } dependencies: call-bind-apply-helpers: 1.0.2 es-define-property: 1.0.1 @@ -1302,20 +1784,29 @@ packages: math-intrinsics: 1.1.0 /get-proto@1.0.1: - resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==, + } + engines: { node: ">= 0.4" } dependencies: dunder-proto: 1.0.1 es-object-atoms: 1.1.1 /get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==, + } + engines: { node: ">=10" } dev: true /get-uri@6.0.5: - resolution: {integrity: sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==} - engines: {node: '>= 14'} + resolution: + { + integrity: sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==, + } + engines: { node: ">= 14" } dependencies: basic-ftp: 5.0.5 data-uri-to-buffer: 6.0.2 @@ -1325,14 +1816,20 @@ packages: dev: true /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} + resolution: + { + integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==, + } + engines: { node: ">= 6" } dependencies: is-glob: 4.0.3 /glob@8.1.0: - resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==, + } + engines: { node: ">=12" } deprecated: Glob versions prior to v9 are no longer supported dependencies: fs.realpath: 1.0.0 @@ -1343,15 +1840,21 @@ packages: dev: true /gopd@1.2.0: - resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==, + } + engines: { node: ">= 0.4" } /got@12.6.1: - resolution: {integrity: sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==} - engines: {node: '>=14.16'} - dependencies: - '@sindresorhus/is': 5.6.0 - '@szmarczak/http-timer': 5.0.1 + resolution: + { + integrity: sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==, + } + engines: { node: ">=14.16" } + dependencies: + "@sindresorhus/is": 5.6.0 + "@szmarczak/http-timer": 5.0.1 cacheable-lookup: 7.0.0 cacheable-request: 10.2.14 decompress-response: 6.0.0 @@ -1364,27 +1867,36 @@ packages: dev: true /graceful-fs@4.2.10: - resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} + resolution: + { + integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==, + } dev: true /graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + resolution: + { + integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==, + } /hardhat-deploy@0.12.4: - resolution: {integrity: sha512-bYO8DIyeGxZWlhnMoCBon9HNZb6ji0jQn7ngP1t5UmGhC8rQYhji7B73qETMOFhzt5ECZPr+U52duj3nubsqdQ==} - dependencies: - '@ethersproject/abi': 5.8.0 - '@ethersproject/abstract-signer': 5.8.0 - '@ethersproject/address': 5.8.0 - '@ethersproject/bignumber': 5.8.0 - '@ethersproject/bytes': 5.8.0 - '@ethersproject/constants': 5.8.0 - '@ethersproject/contracts': 5.8.0 - '@ethersproject/providers': 5.8.0 - '@ethersproject/solidity': 5.8.0 - '@ethersproject/transactions': 5.8.0 - '@ethersproject/wallet': 5.8.0 - '@types/qs': 6.14.0 + resolution: + { + integrity: sha512-bYO8DIyeGxZWlhnMoCBon9HNZb6ji0jQn7ngP1t5UmGhC8rQYhji7B73qETMOFhzt5ECZPr+U52duj3nubsqdQ==, + } + dependencies: + "@ethersproject/abi": 5.8.0 + "@ethersproject/abstract-signer": 5.8.0 + "@ethersproject/address": 5.8.0 + "@ethersproject/bignumber": 5.8.0 + "@ethersproject/bytes": 5.8.0 + "@ethersproject/constants": 5.8.0 + "@ethersproject/contracts": 5.8.0 + "@ethersproject/providers": 5.8.0 + "@ethersproject/solidity": 5.8.0 + "@ethersproject/transactions": 5.8.0 + "@ethersproject/wallet": 5.8.0 + "@types/qs": 6.14.0 axios: 0.21.4(debug@4.4.1) chalk: 4.1.2 chokidar: 3.6.0 @@ -1403,46 +1915,70 @@ packages: - utf-8-validate /has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==, + } + engines: { node: ">=8" } /has-symbols@1.1.0: - resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==, + } + engines: { node: ">= 0.4" } /has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==, + } + engines: { node: ">= 0.4" } dependencies: has-symbols: 1.1.0 /hash.js@1.1.7: - resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} + resolution: + { + integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==, + } dependencies: inherits: 2.0.4 minimalistic-assert: 1.0.1 /hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==, + } + engines: { node: ">= 0.4" } dependencies: function-bind: 1.1.2 /hmac-drbg@1.0.1: - resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} + resolution: + { + integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==, + } dependencies: hash.js: 1.1.7 minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 /html-link-extractor@1.0.5: - resolution: {integrity: sha512-ADd49pudM157uWHwHQPUSX4ssMsvR/yHIswOR5CUfBdK9g9ZYGMhVSE6KZVHJ6kCkR0gH4htsfzU6zECDNVwyw==} + resolution: + { + integrity: sha512-ADd49pudM157uWHwHQPUSX4ssMsvR/yHIswOR5CUfBdK9g9ZYGMhVSE6KZVHJ6kCkR0gH4htsfzU6zECDNVwyw==, + } dependencies: cheerio: 1.1.0 dev: true /htmlparser2@10.0.0: - resolution: {integrity: sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==} + resolution: + { + integrity: sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==, + } dependencies: domelementtype: 2.3.0 domhandler: 5.0.3 @@ -1451,12 +1987,18 @@ packages: dev: true /http-cache-semantics@4.2.0: - resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==} + resolution: + { + integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==, + } dev: true /http-proxy-agent@7.0.2: - resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} - engines: {node: '>= 14'} + resolution: + { + integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==, + } + engines: { node: ">= 14" } dependencies: agent-base: 7.1.4 debug: 4.4.1 @@ -1465,16 +2007,22 @@ packages: dev: true /http2-wrapper@2.2.1: - resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==} - engines: {node: '>=10.19.0'} + resolution: + { + integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==, + } + engines: { node: ">=10.19.0" } dependencies: quick-lru: 5.1.1 resolve-alpn: 1.2.1 dev: true /https-proxy-agent@7.0.6: - resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} - engines: {node: '>= 14'} + resolution: + { + integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==, + } + engines: { node: ">= 14" } dependencies: agent-base: 7.1.4 debug: 4.4.1 @@ -1483,31 +2031,46 @@ packages: dev: true /iconv-lite@0.6.3: - resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==, + } + engines: { node: ">=0.10.0" } dependencies: safer-buffer: 2.1.2 dev: true /ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} - engines: {node: '>= 4'} + resolution: + { + integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==, + } + engines: { node: ">= 4" } dev: true /import-fresh@3.3.1: - resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==, + } + engines: { node: ">=6" } dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 dev: true /imul@1.0.1: - resolution: {integrity: sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA==, + } + engines: { node: ">=0.10.0" } /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + resolution: + { + integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==, + } deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. dependencies: once: 1.4.0 @@ -1515,70 +2078,112 @@ packages: dev: true /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + resolution: + { + integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==, + } /ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + resolution: + { + integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==, + } dev: true /ip-address@9.0.5: - resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} - engines: {node: '>= 12'} + resolution: + { + integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==, + } + engines: { node: ">= 12" } dependencies: jsbn: 1.1.0 sprintf-js: 1.1.3 dev: true /is-absolute-url@4.0.1: - resolution: {integrity: sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + resolution: + { + integrity: sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==, + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } dev: true /is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + resolution: + { + integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==, + } dev: true /is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==, + } + engines: { node: ">=8" } dependencies: binary-extensions: 2.3.0 /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==, + } + engines: { node: ">=0.10.0" } /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==, + } + engines: { node: ">=8" } dev: true /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==, + } + engines: { node: ">=0.10.0" } dependencies: is-extglob: 2.1.1 /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} + resolution: + { + integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==, + } + engines: { node: ">=0.12.0" } /is-relative-url@4.0.0: - resolution: {integrity: sha512-PkzoL1qKAYXNFct5IKdKRH/iBQou/oCC85QhXj6WKtUQBliZ4Yfd3Zk27RHu9KQG8r6zgvAA2AQKC9p+rqTszg==} - engines: {node: '>=14.16'} + resolution: + { + integrity: sha512-PkzoL1qKAYXNFct5IKdKRH/iBQou/oCC85QhXj6WKtUQBliZ4Yfd3Zk27RHu9KQG8r6zgvAA2AQKC9p+rqTszg==, + } + engines: { node: ">=14.16" } dependencies: is-absolute-url: 4.0.1 dev: true /js-sha3@0.8.0: - resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} + resolution: + { + integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==, + } /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + resolution: + { + integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==, + } dev: true /js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + resolution: + { + integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==, + } hasBin: true dependencies: argparse: 1.0.10 @@ -1586,68 +2191,107 @@ packages: dev: true /js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + resolution: + { + integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==, + } hasBin: true dependencies: argparse: 2.0.1 dev: true /jsbn@1.1.0: - resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} + resolution: + { + integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==, + } dev: true /json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + resolution: + { + integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==, + } dev: true /json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + resolution: + { + integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==, + } dev: true /json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + resolution: + { + integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==, + } dev: true /json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + resolution: + { + integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==, + } dev: true /jsonfile@6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + resolution: + { + integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==, + } dependencies: universalify: 2.0.1 optionalDependencies: graceful-fs: 4.2.11 /jsonpointer@5.0.1: - resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==, + } + engines: { node: ">=0.10.0" } dev: true /keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + resolution: + { + integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==, + } dependencies: json-buffer: 3.0.1 dev: true /latest-version@7.0.0: - resolution: {integrity: sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==} - engines: {node: '>=14.16'} + resolution: + { + integrity: sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==, + } + engines: { node: ">=14.16" } dependencies: package-json: 8.1.1 dev: true /leven@3.1.0: - resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==, + } + engines: { node: ">=6" } dev: true /lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + resolution: + { + integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==, + } dev: true /link-check@5.4.0: - resolution: {integrity: sha512-0Pf4xBVUnwJdbDgpBlhHNmWDtbVjHTpIFs+JaBuIsC9PKRxjv4KMGCO2Gc8lkVnqMf9B/yaNY+9zmMlO5MyToQ==} + resolution: + { + integrity: sha512-0Pf4xBVUnwJdbDgpBlhHNmWDtbVjHTpIFs+JaBuIsC9PKRxjv4KMGCO2Gc8lkVnqMf9B/yaNY+9zmMlO5MyToQ==, + } dependencies: is-relative-url: 4.0.0 ms: 2.1.3 @@ -1659,30 +2303,48 @@ packages: dev: true /lodash.truncate@4.4.2: - resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} + resolution: + { + integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==, + } dev: true /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + resolution: + { + integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==, + } dev: true /loupe@2.3.7: - resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} + resolution: + { + integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==, + } dependencies: get-func-name: 2.0.2 /lowercase-keys@3.0.0: - resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + resolution: + { + integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==, + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } dev: true /lru-cache@7.18.3: - resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==, + } + engines: { node: ">=12" } dev: true /markdown-link-check@3.13.7: - resolution: {integrity: sha512-Btn3HU8s2Uyh1ZfzmyZEkp64zp2+RAjwfQt1u4swq2Xa6w37OW0T2inQZrkSNVxDSa2jSN2YYhw/JkAp5jF1PQ==} + resolution: + { + integrity: sha512-Btn3HU8s2Uyh1ZfzmyZEkp64zp2+RAjwfQt1u4swq2Xa6w37OW0T2inQZrkSNVxDSa2jSN2YYhw/JkAp5jF1PQ==, + } hasBin: true dependencies: async: 3.2.6 @@ -1699,75 +2361,120 @@ packages: dev: true /markdown-link-extractor@4.0.2: - resolution: {integrity: sha512-5cUOu4Vwx1wenJgxaudsJ8xwLUMN7747yDJX3V/L7+gi3e4MsCm7w5nbrDQQy8nEfnl4r5NV3pDXMAjhGXYXAw==} + resolution: + { + integrity: sha512-5cUOu4Vwx1wenJgxaudsJ8xwLUMN7747yDJX3V/L7+gi3e4MsCm7w5nbrDQQy8nEfnl4r5NV3pDXMAjhGXYXAw==, + } dependencies: html-link-extractor: 1.0.5 marked: 12.0.2 dev: true /marked@12.0.2: - resolution: {integrity: sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==} - engines: {node: '>= 18'} + resolution: + { + integrity: sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==, + } + engines: { node: ">= 18" } hasBin: true dev: true /match-all@1.2.7: - resolution: {integrity: sha512-qSpsBKarh55r9KyXzFC3xBLRf2GlGasba2em9kbpRsSlGvdTAqjx3QD0r3FKSARiW+OE4iMHYsolM3aX9n5djw==} + resolution: + { + integrity: sha512-qSpsBKarh55r9KyXzFC3xBLRf2GlGasba2em9kbpRsSlGvdTAqjx3QD0r3FKSARiW+OE4iMHYsolM3aX9n5djw==, + } /math-intrinsics@1.1.0: - resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==, + } + engines: { node: ">= 0.4" } /mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} + resolution: + { + integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==, + } + engines: { node: ">= 0.6" } /mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} + resolution: + { + integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==, + } + engines: { node: ">= 0.6" } dependencies: mime-db: 1.52.0 /mimic-response@3.1.0: - resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==, + } + engines: { node: ">=10" } dev: true /mimic-response@4.0.0: - resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + resolution: + { + integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==, + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } dev: true /minimalistic-assert@1.0.1: - resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + resolution: + { + integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==, + } /minimalistic-crypto-utils@1.0.1: - resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} + resolution: + { + integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==, + } /minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==, + } + engines: { node: ">=10" } dependencies: brace-expansion: 2.0.2 dev: true /minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + resolution: + { + integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==, + } dev: true /ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + resolution: + { + integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==, + } /murmur-128@0.2.1: - resolution: {integrity: sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg==} + resolution: + { + integrity: sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg==, + } dependencies: encode-utf8: 1.0.3 fmix: 0.1.0 imul: 1.0.1 /needle@3.3.1: - resolution: {integrity: sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==} - engines: {node: '>= 4.4.x'} + resolution: + { + integrity: sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==, + } + engines: { node: ">= 4.4.x" } hasBin: true dependencies: iconv-lite: 0.6.3 @@ -1775,53 +2482,80 @@ packages: dev: true /netmask@2.0.2: - resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} - engines: {node: '>= 0.4.0'} + resolution: + { + integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==, + } + engines: { node: ">= 0.4.0" } dev: true /node-email-verifier@2.0.0: - resolution: {integrity: sha512-AHcppjOH2KT0mxakrxFMOMjV/gOVMRpYvnJUkNfgF9oJ3INdVmqcMFJ5TlM8elpTPwt6A7bSp1IMnnWcxGom/Q==} - engines: {node: '>=16.0.0'} + resolution: + { + integrity: sha512-AHcppjOH2KT0mxakrxFMOMjV/gOVMRpYvnJUkNfgF9oJ3INdVmqcMFJ5TlM8elpTPwt6A7bSp1IMnnWcxGom/Q==, + } + engines: { node: ">=16.0.0" } dependencies: ms: 2.1.3 validator: 13.15.15 dev: true /normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==, + } + engines: { node: ">=0.10.0" } /normalize-url@8.0.2: - resolution: {integrity: sha512-Ee/R3SyN4BuynXcnTaekmaVdbDAEiNrHqjQIA37mHU8G9pf7aaAD4ZX3XjBLo6rsdcxA/gtkcNYZLt30ACgynw==} - engines: {node: '>=14.16'} + resolution: + { + integrity: sha512-Ee/R3SyN4BuynXcnTaekmaVdbDAEiNrHqjQIA37mHU8G9pf7aaAD4ZX3XjBLo6rsdcxA/gtkcNYZLt30ACgynw==, + } + engines: { node: ">=14.16" } dev: true /nth-check@2.1.1: - resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + resolution: + { + integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==, + } dependencies: boolbase: 1.0.0 dev: true /object-inspect@1.13.4: - resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==, + } + engines: { node: ">= 0.4" } /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + resolution: + { + integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==, + } dependencies: wrappy: 1.0.2 dev: true /p-cancelable@3.0.0: - resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==} - engines: {node: '>=12.20'} + resolution: + { + integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==, + } + engines: { node: ">=12.20" } dev: true /pac-proxy-agent@7.2.0: - resolution: {integrity: sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==} - engines: {node: '>= 14'} + resolution: + { + integrity: sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==, + } + engines: { node: ">= 14" } dependencies: - '@tootallnate/quickjs-emscripten': 0.23.0 + "@tootallnate/quickjs-emscripten": 0.23.0 agent-base: 7.1.4 debug: 4.4.1 get-uri: 6.0.5 @@ -1834,16 +2568,22 @@ packages: dev: true /pac-resolver@7.0.1: - resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==} - engines: {node: '>= 14'} + resolution: + { + integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==, + } + engines: { node: ">= 14" } dependencies: degenerator: 5.0.1 netmask: 2.0.2 dev: true /package-json@8.1.1: - resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==} - engines: {node: '>=14.16'} + resolution: + { + integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==, + } + engines: { node: ">=14.16" } dependencies: got: 12.6.1 registry-auth-token: 5.1.0 @@ -1852,91 +2592,136 @@ packages: dev: true /parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==, + } + engines: { node: ">=6" } dependencies: callsites: 3.1.0 dev: true /parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==, + } + engines: { node: ">=8" } dependencies: - '@babel/code-frame': 7.27.1 + "@babel/code-frame": 7.27.1 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 dev: true /parse5-htmlparser2-tree-adapter@7.1.0: - resolution: {integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==} + resolution: + { + integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==, + } dependencies: domhandler: 5.0.3 parse5: 7.3.0 dev: true /parse5-parser-stream@7.1.2: - resolution: {integrity: sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==} + resolution: + { + integrity: sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==, + } dependencies: parse5: 7.3.0 dev: true /parse5@7.3.0: - resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + resolution: + { + integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==, + } dependencies: entities: 6.0.1 dev: true /path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==, + } + engines: { node: ">=8" } dev: true /pathval@1.1.1: - resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + resolution: + { + integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==, + } /picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + resolution: + { + integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==, + } dev: true /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} + resolution: + { + integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==, + } + engines: { node: ">=8.6" } /pluralize@8.0.0: - resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==, + } + engines: { node: ">=4" } dev: true /prettier-plugin-solidity@1.4.3(prettier@2.8.8): - resolution: {integrity: sha512-Mrr/iiR9f9IaeGRMZY2ApumXcn/C5Gs3S7B7hWB3gigBFML06C0yEyW86oLp0eqiA0qg+46FaChgLPJCj/pIlg==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-Mrr/iiR9f9IaeGRMZY2ApumXcn/C5Gs3S7B7hWB3gigBFML06C0yEyW86oLp0eqiA0qg+46FaChgLPJCj/pIlg==, + } + engines: { node: ">=18" } peerDependencies: - prettier: '>=2.3.0' + prettier: ">=2.3.0" dependencies: - '@solidity-parser/parser': 0.20.1 + "@solidity-parser/parser": 0.20.1 prettier: 2.8.8 semver: 7.7.2 dev: true /prettier@2.8.8: - resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} - engines: {node: '>=10.13.0'} + resolution: + { + integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==, + } + engines: { node: ">=10.13.0" } hasBin: true dev: true /progress@2.0.3: - resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} - engines: {node: '>=0.4.0'} + resolution: + { + integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==, + } + engines: { node: ">=0.4.0" } dev: true /proto-list@1.2.4: - resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + resolution: + { + integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==, + } dev: true /proxy-agent@6.5.0: - resolution: {integrity: sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==} - engines: {node: '>= 14'} + resolution: + { + integrity: sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==, + } + engines: { node: ">= 14" } dependencies: agent-base: 7.1.4 debug: 4.4.1 @@ -1951,27 +2736,42 @@ packages: dev: true /proxy-from-env@1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + resolution: + { + integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==, + } dev: true /punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} + resolution: + { + integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==, + } + engines: { node: ">=6" } dev: true /qs@6.14.0: - resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} - engines: {node: '>=0.6'} + resolution: + { + integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==, + } + engines: { node: ">=0.6" } dependencies: side-channel: 1.1.0 /quick-lru@5.1.1: - resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==, + } + engines: { node: ">=10" } dev: true /rc@1.2.8: - resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + resolution: + { + integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==, + } hasBin: true dependencies: deep-extend: 0.6.0 @@ -1981,73 +2781,112 @@ packages: dev: true /readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} + resolution: + { + integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==, + } + engines: { node: ">=8.10.0" } dependencies: picomatch: 2.3.1 /registry-auth-token@5.1.0: - resolution: {integrity: sha512-GdekYuwLXLxMuFTwAPg5UKGLW/UXzQrZvH/Zj791BQif5T05T0RsaLfHc9q3ZOKi7n+BoprPD9mJ0O0k4xzUlw==} - engines: {node: '>=14'} + resolution: + { + integrity: sha512-GdekYuwLXLxMuFTwAPg5UKGLW/UXzQrZvH/Zj791BQif5T05T0RsaLfHc9q3ZOKi7n+BoprPD9mJ0O0k4xzUlw==, + } + engines: { node: ">=14" } dependencies: - '@pnpm/npm-conf': 2.3.1 + "@pnpm/npm-conf": 2.3.1 dev: true /registry-url@6.0.1: - resolution: {integrity: sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==} - engines: {node: '>=12'} + resolution: + { + integrity: sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==, + } + engines: { node: ">=12" } dependencies: rc: 1.2.8 dev: true /require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==, + } + engines: { node: ">=0.10.0" } dev: true /resolve-alpn@1.2.1: - resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} + resolution: + { + integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==, + } dev: true /resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==, + } + engines: { node: ">=4" } dev: true /responselike@3.0.0: - resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==} - engines: {node: '>=14.16'} + resolution: + { + integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==, + } + engines: { node: ">=14.16" } dependencies: lowercase-keys: 3.0.0 dev: true /safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + resolution: + { + integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==, + } dev: true /sax@1.4.1: - resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} + resolution: + { + integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==, + } dev: true /scrypt-js@3.0.1: - resolution: {integrity: sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==} + resolution: + { + integrity: sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==, + } /semver@7.7.2: - resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==, + } + engines: { node: ">=10" } hasBin: true dev: true /side-channel-list@1.0.0: - resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==, + } + engines: { node: ">= 0.4" } dependencies: es-errors: 1.3.0 object-inspect: 1.13.4 /side-channel-map@1.0.1: - resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==, + } + engines: { node: ">= 0.4" } dependencies: call-bound: 1.0.4 es-errors: 1.3.0 @@ -2055,8 +2894,11 @@ packages: object-inspect: 1.13.4 /side-channel-weakmap@1.0.2: - resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==, + } + engines: { node: ">= 0.4" } dependencies: call-bound: 1.0.4 es-errors: 1.3.0 @@ -2065,8 +2907,11 @@ packages: side-channel-map: 1.0.1 /side-channel@1.1.0: - resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} - engines: {node: '>= 0.4'} + resolution: + { + integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==, + } + engines: { node: ">= 0.4" } dependencies: es-errors: 1.3.0 object-inspect: 1.13.4 @@ -2075,8 +2920,11 @@ packages: side-channel-weakmap: 1.0.2 /slice-ansi@4.0.0: - resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} - engines: {node: '>=10'} + resolution: + { + integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==, + } + engines: { node: ">=10" } dependencies: ansi-styles: 4.3.0 astral-regex: 2.0.0 @@ -2084,13 +2932,19 @@ packages: dev: true /smart-buffer@4.2.0: - resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} - engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + resolution: + { + integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==, + } + engines: { node: ">= 6.0.0", npm: ">= 3.0.0" } dev: true /socks-proxy-agent@8.0.5: - resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==} - engines: {node: '>= 14'} + resolution: + { + integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==, + } + engines: { node: ">= 14" } dependencies: agent-base: 7.1.4 debug: 4.4.1 @@ -2100,18 +2954,24 @@ packages: dev: true /socks@2.8.5: - resolution: {integrity: sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww==} - engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + resolution: + { + integrity: sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww==, + } + engines: { node: ">= 10.0.0", npm: ">= 3.0.0" } dependencies: ip-address: 9.0.5 smart-buffer: 4.2.0 dev: true /solhint@5.2.0: - resolution: {integrity: sha512-9NZC1zt+O2K7zEZOhTT9rFeB6GdxC6qTX5pWX70RaQoflR9RejJQUC+/19LNi+e7K9Ptb4k7XAWO9wY5mkprHg==} + resolution: + { + integrity: sha512-9NZC1zt+O2K7zEZOhTT9rFeB6GdxC6qTX5pWX70RaQoflR9RejJQUC+/19LNi+e7K9Ptb4k7XAWO9wY5mkprHg==, + } hasBin: true dependencies: - '@solidity-parser/parser': 0.20.1 + "@solidity-parser/parser": 0.20.1 ajv: 6.12.6 ajv-errors: 1.0.1(ajv@6.12.6) antlr4: 4.13.2 @@ -2139,30 +2999,48 @@ packages: dev: true /solidity-bytes-utils@0.8.4: - resolution: {integrity: sha512-/bjac5YR12i0plOKvGlhE51F5IWGP6rI8DJetCQlXcnwKWz/Hgf/vr+Qlk1BWz56xVcwVhmhCaDkTMnx5xvt0g==} + resolution: + { + integrity: sha512-/bjac5YR12i0plOKvGlhE51F5IWGP6rI8DJetCQlXcnwKWz/Hgf/vr+Qlk1BWz56xVcwVhmhCaDkTMnx5xvt0g==, + } /solmate@6.8.0: - resolution: {integrity: sha512-/oI8kgEvSxGG1mrFv3FmCEZd0F8Z9VzRmoYMIhzmmzt6mjtPwfdCm3oh8yOL7bMHJBSfXJuMpnMPrM0uyaKsKg==} + resolution: + { + integrity: sha512-/oI8kgEvSxGG1mrFv3FmCEZd0F8Z9VzRmoYMIhzmmzt6mjtPwfdCm3oh8yOL7bMHJBSfXJuMpnMPrM0uyaKsKg==, + } dev: true /source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==, + } + engines: { node: ">=0.10.0" } requiresBuild: true dev: true optional: true /sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + resolution: + { + integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==, + } dev: true /sprintf-js@1.1.3: - resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + resolution: + { + integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==, + } dev: true /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==, + } + engines: { node: ">=8" } dependencies: emoji-regex: 8.0.0 is-fullwidth-code-point: 3.0.0 @@ -2170,25 +3048,37 @@ packages: dev: true /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==, + } + engines: { node: ">=8" } dependencies: ansi-regex: 5.0.1 /strip-json-comments@2.0.1: - resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} - engines: {node: '>=0.10.0'} + resolution: + { + integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==, + } + engines: { node: ">=0.10.0" } dev: true /supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} + resolution: + { + integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==, + } + engines: { node: ">=8" } dependencies: has-flag: 4.0.0 /table@6.9.0: - resolution: {integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==} - engines: {node: '>=10.0.0'} + resolution: + { + integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==, + } + engines: { node: ">=10.0.0" } dependencies: ajv: 8.17.1 lodash.truncate: 4.4.2 @@ -2198,65 +3088,101 @@ packages: dev: true /text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + resolution: + { + integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==, + } dev: true /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} + resolution: + { + integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==, + } + engines: { node: ">=8.0" } dependencies: is-number: 7.0.0 /tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + resolution: + { + integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==, + } dev: true /type-detect@4.1.0: - resolution: {integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==} - engines: {node: '>=4'} + resolution: + { + integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==, + } + engines: { node: ">=4" } /undici@7.11.0: - resolution: {integrity: sha512-heTSIac3iLhsmZhUCjyS3JQEkZELateufzZuBaVM5RHXdSBMb1LPMQf5x+FH7qjsZYDP0ttAc3nnVpUB+wYbOg==} - engines: {node: '>=20.18.1'} + resolution: + { + integrity: sha512-heTSIac3iLhsmZhUCjyS3JQEkZELateufzZuBaVM5RHXdSBMb1LPMQf5x+FH7qjsZYDP0ttAc3nnVpUB+wYbOg==, + } + engines: { node: ">=20.18.1" } dev: true /universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} + resolution: + { + integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==, + } + engines: { node: ">= 10.0.0" } /uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + resolution: + { + integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==, + } dependencies: punycode: 2.3.1 dev: true /validator@13.15.15: - resolution: {integrity: sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A==} - engines: {node: '>= 0.10'} + resolution: + { + integrity: sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A==, + } + engines: { node: ">= 0.10" } dev: true /whatwg-encoding@3.1.1: - resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==, + } + engines: { node: ">=18" } dependencies: iconv-lite: 0.6.3 dev: true /whatwg-mimetype@4.0.0: - resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} - engines: {node: '>=18'} + resolution: + { + integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==, + } + engines: { node: ">=18" } dev: true /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + resolution: + { + integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==, + } dev: true /ws@8.18.0: - resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} - engines: {node: '>=10.0.0'} + resolution: + { + integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==, + } + engines: { node: ">=10.0.0" } peerDependencies: bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' + utf-8-validate: ">=5.0.2" peerDependenciesMeta: bufferutil: optional: true @@ -2264,47 +3190,52 @@ packages: optional: true /xmlbuilder2@3.1.1: - resolution: {integrity: sha512-WCSfbfZnQDdLQLiMdGUQpMxxckeQ4oZNMNhLVkcekTu7xhD4tuUDyAPoY8CwXvBYE6LwBHd6QW2WZXlOWr1vCw==} - engines: {node: '>=12.0'} - dependencies: - '@oozcitak/dom': 1.15.10 - '@oozcitak/infra': 1.0.8 - '@oozcitak/util': 8.3.8 + resolution: + { + integrity: sha512-WCSfbfZnQDdLQLiMdGUQpMxxckeQ4oZNMNhLVkcekTu7xhD4tuUDyAPoY8CwXvBYE6LwBHd6QW2WZXlOWr1vCw==, + } + engines: { node: ">=12.0" } + dependencies: + "@oozcitak/dom": 1.15.10 + "@oozcitak/infra": 1.0.8 + "@oozcitak/util": 8.3.8 js-yaml: 3.14.1 dev: true /zksync-ethers@5.10.0(ethers@5.8.0): - resolution: {integrity: sha512-OAjTGAHF9wbdkRGkj7XZuF/a1Sk/FVbwH4pmLjAKlR7mJ7sQtQhBhrPU2dCc67xLaNvEESPfwil19ES5wooYFg==} - engines: {node: '>=16.0.0'} + resolution: + { + integrity: sha512-OAjTGAHF9wbdkRGkj7XZuF/a1Sk/FVbwH4pmLjAKlR7mJ7sQtQhBhrPU2dCc67xLaNvEESPfwil19ES5wooYFg==, + } + engines: { node: ">=16.0.0" } peerDependencies: ethers: ~5.7.0 dependencies: ethers: 5.8.0 github.com/Arachnid/solidity-stringutils/4b2fcc43fa0426e19ce88b1f1ec16f5903a2e461: - resolution: {tarball: https://codeload.github.com/Arachnid/solidity-stringutils/tar.gz/4b2fcc43fa0426e19ce88b1f1ec16f5903a2e461} + resolution: + { + tarball: https://codeload.github.com/Arachnid/solidity-stringutils/tar.gz/4b2fcc43fa0426e19ce88b1f1ec16f5903a2e461, + } name: solidity-stringutils version: 0.0.0 dev: false - github.com/PufferFinance/rave/57ce268: - resolution: {tarball: https://codeload.github.com/PufferFinance/rave/tar.gz/57ce268} - name: rave.git#57ce268 - version: 0.0.0 - dev: false - github.com/a16z/erc4626-tests/232ff9b: - resolution: {tarball: https://codeload.github.com/a16z/erc4626-tests/tar.gz/232ff9b} + resolution: + { tarball: https://codeload.github.com/a16z/erc4626-tests/tar.gz/232ff9b } name: erc4626-tests#232ff9b version: 0.0.0 dev: true github.com/crytic/properties/f1ff61b: - resolution: {tarball: https://codeload.github.com/crytic/properties/tar.gz/f1ff61b} - name: '@crytic/properties' + resolution: + { tarball: https://codeload.github.com/crytic/properties/tar.gz/f1ff61b } + name: "@crytic/properties" version: 0.0.1 dependencies: - '@openzeppelin/contracts': 4.9.6 + "@openzeppelin/contracts": 4.9.6 markdown-link-check: 3.13.7 prettier: 2.8.8 prettier-plugin-solidity: 1.4.3(prettier@2.8.8) @@ -2314,19 +3245,26 @@ packages: dev: true github.com/dmfxyz/murky/991e371eb1dfa9f86701869eb08ec4e98c3cc0b0: - resolution: {tarball: https://codeload.github.com/dmfxyz/murky/tar.gz/991e371eb1dfa9f86701869eb08ec4e98c3cc0b0} + resolution: + { + tarball: https://codeload.github.com/dmfxyz/murky/tar.gz/991e371eb1dfa9f86701869eb08ec4e98c3cc0b0, + } name: murky version: 0.1.0 dev: false github.com/evmcheb/solarray/a547630: - resolution: {tarball: https://codeload.github.com/evmcheb/solarray/tar.gz/a547630} + resolution: + { tarball: https://codeload.github.com/evmcheb/solarray/tar.gz/a547630 } name: solarray version: 1.0.0 dev: true github.com/foundry-rs/forge-std/3b20d60d14b343ee4f908cb8079495c07f5e8981: - resolution: {tarball: https://codeload.github.com/foundry-rs/forge-std/tar.gz/3b20d60d14b343ee4f908cb8079495c07f5e8981} + resolution: + { + tarball: https://codeload.github.com/foundry-rs/forge-std/tar.gz/3b20d60d14b343ee4f908cb8079495c07f5e8981, + } name: forge-std version: 1.9.6 dev: true diff --git a/mainnet-contracts/src/EnclaveVerifier.sol b/mainnet-contracts/src/EnclaveVerifier.sol deleted file mode 100644 index 1c52a239..00000000 --- a/mainnet-contracts/src/EnclaveVerifier.sol +++ /dev/null @@ -1,105 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity >=0.8.0 <0.9.0; - -import { RAVE } from "rave/RAVE.sol"; -import { X509Verifier } from "rave/X509Verifier.sol"; -import { IEnclaveVerifier } from "./interface/IEnclaveVerifier.sol"; -import { RaveEvidence } from "./struct/RaveEvidence.sol"; -import { AccessManaged } from "@openzeppelin/contracts/access/manager/AccessManaged.sol"; -import { InvalidAddress } from "./Errors.sol"; - -/** - * @title EnclaveVerifier - * @author Puffer Finance - * @custom:security-contact security@puffer.fi - */ -contract EnclaveVerifier is IEnclaveVerifier, AccessManaged, RAVE { - /** - * @dev RSA Public key for Intel: https://api.portal.trustedservices.intel.com/content/documentation.html - */ - bytes internal constant _INTEL_RSA_MODULUS = - hex"9F3C647EB5773CBB512D2732C0D7415EBB55A0FA9EDE2E649199E6821DB910D53177370977466A6A5E4786CCD2DDEBD4149D6A2F6325529DD10CC98737B0779C1A07E29C47A1AE004948476C489F45A5A15D7AC8ECC6ACC645ADB43D87679DF59C093BC5A2E9696C5478541B979E754B573914BE55D32FF4C09DDF27219934CD990527B3F92ED78FBF29246ABECB71240EF39C2D7107B447545A7FFB10EB060A68A98580219E36910952683892D6A5E2A80803193E407531404E36B315623799AA825074409754A2DFE8F5AFD5FE631E1FC2AF3808906F28A790D9DD9FE060939B125790C5805D037DF56A99531B96DE69DE33ED226CC1207D1042B5C9AB7F404FC711C0FE4769FB9578B1DC0EC469EA1A25E0FF9914886EF2699B235BB4847DD6FF40B606E6170793C2FB98B314587F9CFD257362DFEAB10B3BD2D97673A1A4BD44C453AAF47FC1F2D3D0F384F74A06F89C089F0DA6CDB7FCEEE8C9821A8E54F25C0416D18C46839A5F8012FBDD3DC74D256279ADC2C0D55AFF6F0622425D1B"; - bytes internal constant _INTEL_EXPONENT = hex"010001"; - - /** - * @notice Freshness number of blocks - */ - uint256 public immutable FRESHNESS_BLOCKS; - - /** - * @dev Mapping from keccak'd leaf x509 to RSA pub key components - * leafHash -> pubKey - */ - mapping(bytes32 leafHash => RSAPubKey pubKey) internal _validLeafX509s; - - constructor(uint256 freshnessBlocks, address accessManager) AccessManaged(accessManager) { - if (address(accessManager) == address(0)) { - revert InvalidAddress(); - } - FRESHNESS_BLOCKS = freshnessBlocks; - } - - /** - * @inheritdoc IEnclaveVerifier - */ - function getIntelRootCAPubKey() external pure returns (RSAPubKey memory) { - return RSAPubKey({ modulus: _INTEL_RSA_MODULUS, exponent: _INTEL_EXPONENT }); - } - - /** - * @inheritdoc IEnclaveVerifier - */ - function addLeafX509(bytes calldata leafX509Cert) external { - (bytes memory leafCertModulus, bytes memory leafCertExponent) = - X509Verifier.verifySignedX509(leafX509Cert, _INTEL_RSA_MODULUS, _INTEL_EXPONENT); - - bytes32 hashedCert = keccak256(leafX509Cert); - - _validLeafX509s[hashedCert] = RSAPubKey({ modulus: leafCertModulus, exponent: leafCertExponent }); - - emit AddedPubKey(hashedCert); - } - - /** - * @notice Removes a whitelisted leaf x509 RSA public key - */ - function removeLeafX509(bytes32 hashedCert) external restricted { - delete _validLeafX509s[hashedCert].modulus; - delete _validLeafX509s[hashedCert].exponent; - emit RemovedPubKey(hashedCert); - } - - /** - * @inheritdoc IEnclaveVerifier - */ - function verifyEvidence( - uint256 blockNumber, - bytes32 raveCommitment, - RaveEvidence calldata evidence, - bytes32 mrenclave, - bytes32 mrsigner - ) external view returns (bool) { - // Check for freshness - if ((block.number - blockNumber) > FRESHNESS_BLOCKS) { - revert StaleEvidence(); - } - - RSAPubKey memory leafX509 = _validLeafX509s[evidence.leafX509CertDigest]; - - // Recover a remote attestation payload if everything is valid - bytes memory recoveredPayload = verifyRemoteAttestation({ - report: evidence.report, - sig: evidence.signature, - signingMod: leafX509.modulus, - signingExp: leafX509.exponent, - mrenclave: mrenclave, - mrsigner: mrsigner - }); - - // Remote attestation payloads are expected to be in the form (32B_Commitment || 32B_BlockHash) - bytes memory expectedPayload = abi.encode(raveCommitment, blockhash(blockNumber)); - - // Compare with the expected payload - return (keccak256(expectedPayload) == keccak256(recoveredPayload)); - } -} diff --git a/mainnet-contracts/src/GuardianModule.sol b/mainnet-contracts/src/GuardianModule.sol index abb1297c..323d5835 100644 --- a/mainnet-contracts/src/GuardianModule.sol +++ b/mainnet-contracts/src/GuardianModule.sol @@ -3,8 +3,6 @@ pragma solidity >=0.8.0 <0.9.0; import { AccessManaged } from "@openzeppelin/contracts/access/manager/AccessManaged.sol"; import { IGuardianModule } from "./interface/IGuardianModule.sol"; -import { IEnclaveVerifier } from "./EnclaveVerifier.sol"; -import { RaveEvidence } from "./struct/RaveEvidence.sol"; import { Unauthorized, InvalidAddress } from "./Errors.sol"; import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import { MessageHashUtils } from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; diff --git a/mainnet-contracts/src/interface/IEnclaveVerifier.sol b/mainnet-contracts/src/interface/IEnclaveVerifier.sol deleted file mode 100644 index eed9fa9e..00000000 --- a/mainnet-contracts/src/interface/IEnclaveVerifier.sol +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity >=0.8.0 <0.9.0; - -import { RaveEvidence } from "../struct/RaveEvidence.sol"; - -/** - * @title IEnclaveVerifier interface - * @author Puffer Finance - * @custom:security-contact security@puffer.fi - */ -interface IEnclaveVerifier { - struct RSAPubKey { - bytes modulus; - bytes exponent; - } - - /** - * @notice Thrown if the Evidence that we're trying to verify is stale - * Evidence should be submitted for the recent block < `FRESHNESS_BLOCKS` - * @dev Signature "0x5d4ad9a9" - */ - error StaleEvidence(); - - /** - * @notice Emitted when the `pubKeyHash` is added to valid pubKeys - * @dev Signature "0x13b85b042d2bb270091da7111e3b3cc407f6b86c85882cf48ae94123cae22b17" - */ - event AddedPubKey(bytes32 indexed pubKeyHash); - - /** - * @notice Emitted when the `pubKeyHash` is removed from valid pubKeys - * @dev Signature "0x0ebd07953ae533bded7d9b0715fa49e0a0ed0a6cef4638a685737ffef8b86254" - */ - event RemovedPubKey(bytes32 indexed pubKeyHash); - - /** - * @notice Getter for intelRootCAPubKey - */ - function getIntelRootCAPubKey() external pure returns (RSAPubKey memory); - - /** - * @notice Adds a leaf x509 RSA public key if the x509 was signed by Intel's root CA - * @param leafX509Cert certificate - */ - function addLeafX509(bytes calldata leafX509Cert) external; - - /** - * @notice Verifies remote attestation evidence: the report contains the expected MRENCLAVE/MRSIGNER values, a valid TCB status, and was signed by an Intel-issued x509 certificate. The report will contain a 64B payload in the form (32B_Commitment || 32B_BlockHash), where 32B_Blockhash is a recent L1 blockhash and 32B_Commitment is a keccak256 hash that the enclave is committing to. The calling contract is expected to precompute raveCommitment from public inputs. The function returns true if the report is valid and the extracted payload matches the expected. - * @param blockNumber is the block number to fetch 32B_Blockhash - * @param raveCommitment is the keccak256 hash commitment 32B_Commitment - * @param evidence is the remote attestation evidence - * @param mrenclave is the MRENCLAVE value expected by the calling contract - * @param mrsigner is the MRSIGNER value expected by the calling contract - * @return true if evidence verification is a success - */ - function verifyEvidence( - uint256 blockNumber, - bytes32 raveCommitment, - RaveEvidence calldata evidence, - bytes32 mrenclave, - bytes32 mrsigner - ) external view returns (bool); -} diff --git a/mainnet-contracts/src/struct/RaveEvidence.sol b/mainnet-contracts/src/struct/RaveEvidence.sol deleted file mode 100644 index ac1a8f75..00000000 --- a/mainnet-contracts/src/struct/RaveEvidence.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity >=0.8.0 <0.9.0; - -struct RaveEvidence { - // Preprocessed remote attestation report - bytes report; - // Preprocessed RSA signature over the report - bytes signature; - // The hash of a whitelisted Intel-signed leaf x509 certificate - bytes32 leafX509CertDigest; -} diff --git a/yarn.lock b/yarn.lock index 94029645..00bb0b58 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8187,10 +8187,6 @@ range-parser@~1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -"rave@https://github.com/PufferFinance/rave.git#57ce268": - version "0.0.0" - resolved "https://github.com/PufferFinance/rave.git#57ce2681e4ca216a3fea6b4a18afdebadce3b21c" - raw-body@2.5.2, raw-body@^2.4.1: version "2.5.2" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" From f422a1ddb2427756c44a67d5bfecd743fd7ffbd8 Mon Sep 17 00:00:00 2001 From: Eladio Date: Thu, 29 Jan 2026 11:20:54 +0100 Subject: [PATCH 14/51] fmt --- mainnet-contracts/src/GuardianModule.sol | 16 +++++----------- .../src/interface/IGuardianModule.sol | 1 - .../src/struct/GuardianModuleStructs.sol | 5 +++-- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/mainnet-contracts/src/GuardianModule.sol b/mainnet-contracts/src/GuardianModule.sol index 323d5835..03812c4c 100644 --- a/mainnet-contracts/src/GuardianModule.sol +++ b/mainnet-contracts/src/GuardianModule.sol @@ -66,7 +66,6 @@ contract GuardianModule is AccessManaged, IGuardianModule { */ mapping(bytes32 hash => GoldenMeasurementInfo info) internal _goldenMeasurements; - constructor(IWorkloadVerifier verifier, address[] memory guardians, uint256 threshold, address pufferAuthority) payable AccessManaged(pufferAuthority) @@ -234,7 +233,6 @@ contract GuardianModule is AccessManaged, IGuardianModule { emit GoldenMeasurementRegistered(hash, info); } - /** * @inheritdoc IGuardianModule * @dev Restricted to the DAO @@ -295,16 +293,12 @@ contract GuardianModule is AccessManaged, IGuardianModule { function rotateGuardianKey( uint256 blockNumber, bytes calldata pubKey, - TdxRegistrationData calldata data // TDX DCAP + TdxRegistrationData calldata data // TDX DCAP ) external payable { - (, bytes32 measurementHash, bytes memory tpmExtraData) = - WORKLOAD_VERIFIER.verifyAttestationAndGetMeasurementHash{value: msg.value}( - data.teeType, - data.teeReportType, - data.cloudType, - data.teeAttestationReport, - data.workloadCollaterals - ); + (, bytes32 measurementHash, bytes memory tpmExtraData) = WORKLOAD_VERIFIER + .verifyAttestationAndGetMeasurementHash{ value: msg.value }( + data.teeType, data.teeReportType, data.cloudType, data.teeAttestationReport, data.workloadCollaterals + ); require(_goldenMeasurements[measurementHash].valid, InvalidMeasurement()); diff --git a/mainnet-contracts/src/interface/IGuardianModule.sol b/mainnet-contracts/src/interface/IGuardianModule.sol index f9a78e8f..009172ec 100644 --- a/mainnet-contracts/src/interface/IGuardianModule.sol +++ b/mainnet-contracts/src/interface/IGuardianModule.sol @@ -271,5 +271,4 @@ interface IGuardianModule { * @return Info of the GoldenMeasurement */ function getGoldenMeasurement(bytes32 hash) external view returns (GoldenMeasurementInfo memory); - } diff --git a/mainnet-contracts/src/struct/GuardianModuleStructs.sol b/mainnet-contracts/src/struct/GuardianModuleStructs.sol index d4ba6821..4d99ccf8 100644 --- a/mainnet-contracts/src/struct/GuardianModuleStructs.sol +++ b/mainnet-contracts/src/struct/GuardianModuleStructs.sol @@ -2,7 +2,8 @@ pragma solidity >=0.8.0 <0.9.0; import { TEEType, TeeReportType, CloudType } from "@automata-network/automata-tee-workload-measurement/lib/LibTEE.sol"; -import { WorkloadCollaterals } from "@automata-network/automata-tee-workload-measurement/interfaces/IWorkloadVerifier.sol"; +import { WorkloadCollaterals } from + "@automata-network/automata-tee-workload-measurement/interfaces/IWorkloadVerifier.sol"; /** * @dev Tdx Registration Data @@ -22,7 +23,7 @@ struct GoldenMeasurementInfo { bool valid; TEEType teeType; CloudType cloudType; - string tag; // e.g., "guardian-v1.0.0" + string tag; // e.g., "guardian-v1.0.0" } /** From 528f93f11a80fdf84c06dae26ec7ae9c56835947 Mon Sep 17 00:00:00 2001 From: Eladio Date: Fri, 30 Jan 2026 14:34:58 +0100 Subject: [PATCH 15/51] Adapt scripts and tests (WIP) --- .../script/DeployEverything.s.sol | 8 +- .../script/DeployGuardians.s.sol | 14 +- mainnet-contracts/script/DeployPuffer.s.sol | 5 +- .../script/DeploymentStructs.sol | 4 +- mainnet-contracts/script/SetupAccess.s.sol | 94 +++++---- .../src/interface/IGuardianModule.sol | 2 - .../test/handlers/PufferProtocolHandler.sol | 1 - .../test/helpers/GuardiansRaveEvidence.sol | 178 ------------------ .../test/helpers/IntegrationTestHelper.sol | 9 +- .../test/helpers/UnitTestHelper.sol | 14 +- .../test/mocks/WorkloadVerifierMock.sol | 16 ++ .../test/unit/EnclaveVerifier.t.sol | 106 ----------- .../test/unit/GuardianModule.t.sol | 3 - 13 files changed, 79 insertions(+), 375 deletions(-) delete mode 100644 mainnet-contracts/test/helpers/GuardiansRaveEvidence.sol create mode 100644 mainnet-contracts/test/mocks/WorkloadVerifierMock.sol delete mode 100644 mainnet-contracts/test/unit/EnclaveVerifier.t.sol diff --git a/mainnet-contracts/script/DeployEverything.s.sol b/mainnet-contracts/script/DeployEverything.s.sol index 8b5edee1..92319b0d 100644 --- a/mainnet-contracts/script/DeployEverything.s.sol +++ b/mainnet-contracts/script/DeployEverything.s.sol @@ -22,12 +22,12 @@ import { MockAeraVault } from "test/mocks/MockAeraVault.sol"; * @author Puffer Finance * @notice Deploys pufETH (upgrade it in test environment), Guardians, Oracle, Puffer, and sets up the access control * @dev Example on how to run the script - * forge script script/DeployEverything.s.sol:DeployEverything --rpc-url=$RPC_URL --sig 'run(address[] calldata, uint256, address)' "[$DEV_WALLET]" 1 $DEV_WALLET --broadcast + * forge script script/DeployEverything.s.sol:DeployEverything --rpc-url=$RPC_URL --sig 'run(address, address[] calldata, uint256, address)' "[$DEV_WALLET]" 1 $DEV_WALLET --broadcast */ contract DeployEverything is BaseScript { address DAO; - function run(address[] calldata guardians, uint256 threshold, address paymaster) + function run(address workloadVerifier, address[] calldata guardians, uint256 threshold, address paymaster) public returns (PufferProtocolDeployment memory, BridgingDeployment memory) { @@ -45,7 +45,7 @@ contract DeployEverything is BaseScript { deployment.accessManager = puffETHDeployment.accessManager; GuardiansDeployment memory guardiansDeployment = - new DeployGuardians().run(AccessManager(puffETHDeployment.accessManager), guardians, threshold); + new DeployGuardians().run(workloadVerifier, AccessManager(puffETHDeployment.accessManager), guardians, threshold); address pufferOracle = new DeployPufferOracle().run( puffETHDeployment.accessManager, guardiansDeployment.guardianModule, puffETHDeployment.pufferVault @@ -92,7 +92,7 @@ contract DeployEverything is BaseScript { vm.serializeAddress(obj, "guardianModule", deployment.guardianModule); vm.serializeAddress(obj, "accessManager", deployment.accessManager); - vm.serializeAddress(obj, "enclaveVerifier", deployment.enclaveVerifier); + vm.serializeAddress(obj, "workloadVerifier", deployment.workloadVerifier); vm.serializeAddress(obj, "moduleBeacon", deployment.beacon); vm.serializeAddress(obj, "moduleManager", deployment.moduleManager); vm.serializeAddress(obj, "validatorTicket", deployment.validatorTicket); diff --git a/mainnet-contracts/script/DeployGuardians.s.sol b/mainnet-contracts/script/DeployGuardians.s.sol index 52280ee0..7961760d 100644 --- a/mainnet-contracts/script/DeployGuardians.s.sol +++ b/mainnet-contracts/script/DeployGuardians.s.sol @@ -3,29 +3,25 @@ pragma solidity >=0.8.0 <0.9.0; import { BaseScript } from "script/BaseScript.s.sol"; import { GuardianModule } from "../src/GuardianModule.sol"; -import { EnclaveVerifier } from "../src/EnclaveVerifier.sol"; import { AccessManager } from "@openzeppelin/contracts/access/manager/AccessManager.sol"; import { GuardiansDeployment } from "./DeploymentStructs.sol"; +import { IWorkloadVerifier } from "@automata-network/automata-tee-workload-measurement/interfaces/IWorkloadVerifier.sol"; -// forge script script/1_DeployGuardians.s.sol:DeployGuardians --rpc-url=$EPHEMERY_RPC_URL --sig 'run(address[] calldata, uint256)' "[0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0]" 1 +// forge script script/1_DeployGuardians.s.sol:DeployGuardians --rpc-url=$EPHEMERY_RPC_URL --sig 'run(address, address, address[] calldata, uint256)' "[0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0]" 1 contract DeployGuardians is BaseScript { - function run(AccessManager accessManager, address[] calldata guardians, uint256 threshold) + function run(IWorkloadVerifier workloadVerifier, AccessManager accessManager, address[] calldata guardians, uint256 threshold) public broadcast returns (GuardiansDeployment memory) { vm.label(address(accessManager), "AccessManager"); - uint256 _freshnessBlocks = vm.envOr("ENCLAVE_VERIFIER_FRESHNESS_BLOCKS", uint256(100)); - - EnclaveVerifier verifier = new EnclaveVerifier(_freshnessBlocks, address(accessManager)); - - GuardianModule module = new GuardianModule(verifier, guardians, threshold, address(accessManager)); + GuardianModule module = new GuardianModule(workloadVerifier, guardians, threshold, address(accessManager)); GuardiansDeployment memory deployment; deployment.accessManager = address(accessManager); deployment.guardianModule = address(module); - deployment.enclaveVerifier = address(verifier); + deployment.workloadVerifier = address(workloadVerifier); return deployment; } diff --git a/mainnet-contracts/script/DeployPuffer.s.sol b/mainnet-contracts/script/DeployPuffer.s.sol index 27b7cf69..70f1227e 100644 --- a/mainnet-contracts/script/DeployPuffer.s.sol +++ b/mainnet-contracts/script/DeployPuffer.s.sol @@ -200,8 +200,7 @@ contract DeployPuffer is BaseScript { vm.label(address(pufferProtocolImpl), "PufferProtocolImplementation"); vm.label(address(moduleManagerProxy), "PufferModuleManager"); vm.label(address(pufferModuleBeacon), "PufferModuleBeacon"); - vm.label(address(guardiansDeployment.enclaveVerifier), "EnclaveVerifier"); - vm.label(address(guardiansDeployment.enclaveVerifier), "EnclaveVerifier"); + vm.label(address(guardiansDeployment.workloadVerifier), "WorkloadVerifier"); // return (pufferProtocol, pool, accessManager); return PufferProtocolDeployment({ @@ -211,7 +210,7 @@ contract DeployPuffer is BaseScript { pufferProtocol: address(proxy), guardianModule: guardiansDeployment.guardianModule, accessManager: guardiansDeployment.accessManager, - enclaveVerifier: guardiansDeployment.enclaveVerifier, + workloadVerifier: guardiansDeployment.workloadVerifier, beacon: address(pufferModuleBeacon), restakingOperatorBeacon: address(restakingOperatorBeacon), moduleManager: address(moduleManagerProxy), diff --git a/mainnet-contracts/script/DeploymentStructs.sol b/mainnet-contracts/script/DeploymentStructs.sol index a650ce47..3c826b07 100644 --- a/mainnet-contracts/script/DeploymentStructs.sol +++ b/mainnet-contracts/script/DeploymentStructs.sol @@ -7,7 +7,7 @@ pragma solidity >=0.8.0 <0.9.0; struct GuardiansDeployment { address accessManager; address guardianModule; - address enclaveVerifier; + address workloadVerifier; } /** @@ -18,7 +18,7 @@ struct PufferProtocolDeployment { address pufferProtocol; address guardianModule; address accessManager; - address enclaveVerifier; + address workloadVerifier; address beacon; // Beacon for Puffer modules address restakingOperatorBeacon; // Beacon for Restaking Operator address moduleManager; diff --git a/mainnet-contracts/script/SetupAccess.s.sol b/mainnet-contracts/script/SetupAccess.s.sol index e0349cc1..2e8dd45e 100644 --- a/mainnet-contracts/script/SetupAccess.s.sol +++ b/mainnet-contracts/script/SetupAccess.s.sol @@ -10,7 +10,6 @@ import { Multicall } from "@openzeppelin/contracts/utils/Multicall.sol"; import { PufferProtocol } from "../src/PufferProtocol.sol"; import { GuardianModule } from "../src/GuardianModule.sol"; import { PufferModuleManager } from "../src/PufferModuleManager.sol"; -import { EnclaveVerifier } from "../src/EnclaveVerifier.sol"; import { PufferOracleV2 } from "../src/PufferOracleV2.sol"; import { PufferProtocolDeployment } from "./DeploymentStructs.sol"; import { ValidatorTicket } from "../src/ValidatorTicket.sol"; @@ -100,43 +99,42 @@ contract SetupAccess is BaseScript { ) internal view returns (bytes[] memory calldatas) { calldatas = new bytes[](30); calldatas[0] = _setupGuardianModuleRoles(); - calldatas[1] = _setupEnclaveVerifierRoles(); - calldatas[2] = rolesCalldatas[0]; - calldatas[3] = rolesCalldatas[1]; - calldatas[4] = rolesCalldatas[2]; - calldatas[5] = rolesCalldatas[3]; - calldatas[6] = rolesCalldatas[4]; - calldatas[7] = rolesCalldatas[5]; - calldatas[8] = rolesCalldatas[6]; - - calldatas[9] = pufferProtocolRoles[0]; - calldatas[10] = pufferProtocolRoles[1]; - calldatas[11] = pufferProtocolRoles[2]; - - calldatas[12] = validatorTicketRoles[0]; - calldatas[13] = validatorTicketRoles[1]; - - calldatas[14] = vaultMainnetAccess[0]; - - calldatas[15] = pufferOracleAccess[0]; - calldatas[16] = pufferOracleAccess[1]; - calldatas[17] = pufferOracleAccess[2]; - - calldatas[18] = moduleManagerAccess[0]; - calldatas[19] = moduleManagerAccess[1]; - - calldatas[20] = roleLabels[0]; - calldatas[21] = roleLabels[1]; - calldatas[22] = roleLabels[2]; - calldatas[23] = roleLabels[3]; - - calldatas[24] = coordinatorAccess[0]; - calldatas[25] = coordinatorAccess[1]; - - calldatas[26] = validatorTicketAccess[0]; - calldatas[27] = validatorTicketAccess[1]; - calldatas[28] = validatorTicketAccess[2]; - calldatas[29] = validatorTicketAccess[3]; + calldatas[1] = rolesCalldatas[0]; + calldatas[2] = rolesCalldatas[1]; + calldatas[3] = rolesCalldatas[2]; + calldatas[4] = rolesCalldatas[3]; + calldatas[5] = rolesCalldatas[4]; + calldatas[6] = rolesCalldatas[5]; + calldatas[7] = rolesCalldatas[6]; + + calldatas[8] = pufferProtocolRoles[0]; + calldatas[9] = pufferProtocolRoles[1]; + calldatas[10] = pufferProtocolRoles[2]; + + calldatas[11] = validatorTicketRoles[0]; + calldatas[12] = validatorTicketRoles[1]; + + calldatas[13] = vaultMainnetAccess[0]; + + calldatas[14] = pufferOracleAccess[0]; + calldatas[15] = pufferOracleAccess[1]; + calldatas[16] = pufferOracleAccess[2]; + + calldatas[17] = moduleManagerAccess[0]; + calldatas[18] = moduleManagerAccess[1]; + + calldatas[19] = roleLabels[0]; + calldatas[20] = roleLabels[1]; + calldatas[21] = roleLabels[2]; + calldatas[22] = roleLabels[3]; + + calldatas[23] = coordinatorAccess[0]; + calldatas[24] = coordinatorAccess[1]; + + calldatas[25] = validatorTicketAccess[0]; + calldatas[26] = validatorTicketAccess[1]; + calldatas[27] = validatorTicketAccess[2]; + calldatas[28] = validatorTicketAccess[3]; } function _labelRoles() internal pure returns (bytes[] memory) { @@ -270,26 +268,18 @@ contract SetupAccess is BaseScript { function _setupGuardianModuleRoles() internal view returns (bytes memory) { bytes4[] memory selectors = new bytes4[](5); - selectors[0] = GuardianModule.setGuardianEnclaveMeasurements.selector; - selectors[1] = GuardianModule.addGuardian.selector; - selectors[2] = GuardianModule.removeGuardian.selector; - selectors[3] = GuardianModule.setEjectionThreshold.selector; - selectors[4] = GuardianModule.setThreshold.selector; + selectors[0] = GuardianModule.registerGoldenMeasurement.selector; + selectors[1] = GuardianModule.deregisterGoldenMeasurement.selector; + selectors[2] = GuardianModule.addGuardian.selector; + selectors[3] = GuardianModule.removeGuardian.selector; + selectors[4] = GuardianModule.setEjectionThreshold.selector; + selectors[5] = GuardianModule.setThreshold.selector; return abi.encodeWithSelector( AccessManager.setTargetFunctionRole.selector, pufferDeployment.guardianModule, selectors, ROLE_ID_DAO ); } - function _setupEnclaveVerifierRoles() internal view returns (bytes memory) { - bytes4[] memory selectors = new bytes4[](1); - selectors[0] = EnclaveVerifier.removeLeafX509.selector; - - return abi.encodeWithSelector( - AccessManager.setTargetFunctionRole.selector, pufferDeployment.enclaveVerifier, selectors, ROLE_ID_DAO - ); - } - function _setupPufferProtocolRoles() internal view returns (bytes[] memory) { bytes[] memory calldatas = new bytes[](3); diff --git a/mainnet-contracts/src/interface/IGuardianModule.sol b/mainnet-contracts/src/interface/IGuardianModule.sol index 009172ec..73573d1a 100644 --- a/mainnet-contracts/src/interface/IGuardianModule.sol +++ b/mainnet-contracts/src/interface/IGuardianModule.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0 <0.9.0; -import { RaveEvidence } from "../struct/RaveEvidence.sol"; -import { IEnclaveVerifier } from "../EnclaveVerifier.sol"; import { StoppedValidatorInfo } from "../struct/StoppedValidatorInfo.sol"; import { TdxRegistrationData, GoldenMeasurementInfo } from "../struct/GuardianModuleStructs.sol"; diff --git a/mainnet-contracts/test/handlers/PufferProtocolHandler.sol b/mainnet-contracts/test/handlers/PufferProtocolHandler.sol index 5c9cc944..95892bcd 100644 --- a/mainnet-contracts/test/handlers/PufferProtocolHandler.sol +++ b/mainnet-contracts/test/handlers/PufferProtocolHandler.sol @@ -4,7 +4,6 @@ pragma solidity >=0.8.0 <0.9.0; import { IPufferProtocol } from "../../src/interface/IPufferProtocol.sol"; import { EnumerableMap } from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; -import { RaveEvidence } from "../../src/struct/RaveEvidence.sol"; import { console } from "forge-std/console.sol"; import { Test } from "forge-std/Test.sol"; import { PufferProtocol } from "../../src/PufferProtocol.sol"; diff --git a/mainnet-contracts/test/helpers/GuardiansRaveEvidence.sol b/mainnet-contracts/test/helpers/GuardiansRaveEvidence.sol deleted file mode 100644 index b12f1af3..00000000 --- a/mainnet-contracts/test/helpers/GuardiansRaveEvidence.sol +++ /dev/null @@ -1,178 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity >=0.8.0 <0.9.0; - -import { MockEvidence } from "rave-test/mocks/MockEvidence.sol"; - -contract Guardian3RaveEvidence is MockEvidence { - function report() public pure override returns (bytes memory) { - // Report is inputted as abi-encoded JSON values - return abi.encode( - "186453210057823126547835745110511429060", - "2023-10-16T20:17:59.516859", - "4", - "EbrM6X6YCH3brjPXT23gVh/I2EG5sVfHYh+S54fb0rrAqVRTiRTOSfLsWSVTZc8wrazGG7oooGoMU7Gj5TEhspNWPNBkpcmwf+3WZYsuncw6eX6Uijk+PzPp3dBQSebHsOEQYDRxGeFuWowvkTo2Z5HTavyoRIrSupBTqDE78HA=", - "https://security-center.intel.com", - "[\"INTEL-SA-00334\",\"INTEL-SA-00615\"]", - "SW_HARDENING_NEEDED", - // Already Base64 decoded off-chain - hex"02000100ac0c00000d000d000000000042616c98d53c9712639447c9b0e7003f0000000000000000000000000000000015150b07ff800e000000000000000000000000000000000000000000000000000000000000000000000000000000000005000000000000001f000000000000008eb70e76a34bf6cbf9deed7f467b4888cc187f1f1f34cce2d11ca54014149a35000000000000000000000000000000000000000000000000000000000000000083d719e77deaca1470f6baf62a4d774303c899db69020f9c70ee1dfc08c7ce9e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008619f6cd837e7e0c5c182235222a6fbce0af1b7aa452ee117f08ee1e2ab8f5600000000000000000000000000000000000000000000000000000000000000000" - ); - } - - // The leaf x509 signing certificate's signature over the report - function sig() public pure override returns (bytes memory) { - // base64 decoded signature as hex - return - hex"2c3c7862299e87f941e5a9a49b96a1bc9e2fec4fc15e9ea64e8c3d6a4894cbef433248ac21402f165062936b12ffd75e6b8c4015c34991b75a558390434dcb70a184e24fec38f50929826281ae31793ea02fc3b51f009906e9febbf20abecee32b2dbb831f677babacbc4057030c4650ad4d83dc5b6b28aef78b49c26777c04820856bd36c514f0e8693c0ba7cd94a191d2418f2b0d7d2533013e5a9815b3cb785b0575648267b7990c070b26614b1de1896ade6391364157ebe06112b7a884ff059586cba4f68a02a2440136e16f5b9b65be0d20823ceb773c92191fc615cbab568b809b5beead47201161238b96815f0e9d2c37c4400e4ac794dcf2b1b3599"; - } - - // The leaf x509 signing certificate used to sign the report - function signingCert() public pure override returns (bytes memory) { - return - hex"308204a130820309a003020102020900d107765d32a3b096300d06092a864886f70d01010b0500307e310b3009060355040613025553310b300906035504080c0243413114301206035504070c0b53616e746120436c617261311a3018060355040a0c11496e74656c20436f72706f726174696f6e3130302e06035504030c27496e74656c20534758204174746573746174696f6e205265706f7274205369676e696e67204341301e170d3136313132323039333635385a170d3236313132303039333635385a307b310b3009060355040613025553310b300906035504080c0243413114301206035504070c0b53616e746120436c617261311a3018060355040a0c11496e74656c20436f72706f726174696f6e312d302b06035504030c24496e74656c20534758204174746573746174696f6e205265706f7274205369676e696e6730820122300d06092a864886f70d01010105000382010f003082010a0282010100a97a2de0e66ea6147c9ee745ac0162686c7192099afc4b3f040fad6de093511d74e802f510d716038157dcaf84f4104bd3fed7e6b8f99c8817fd1ff5b9b864296c3d81fa8f1b729e02d21d72ffee4ced725efe74bea68fbc4d4244286fcdd4bf64406a439a15bcb4cf67754489c423972b4a80df5c2e7c5bc2dbaf2d42bb7b244f7c95bf92c75d3b33fc5410678a89589d1083da3acc459f2704cd99598c275e7c1878e00757e5bdb4e840226c11c0a17ff79c80b15c1ddb5af21cc2417061fbd2a2da819ed3b72b7efaa3bfebe2805c9b8ac19aa346512d484cfc81941e15f55881cc127e8f7aa12300cd5afb5742fa1d20cb467a5beb1c666cf76a368978b50203010001a381a43081a1301f0603551d2304183016801478437b76a67ebcd0af7e4237eb357c3b8701513c300e0603551d0f0101ff0404030206c0300c0603551d130101ff0402300030600603551d1f045930573055a053a051864f687474703a2f2f7472757374656473657276696365732e696e74656c2e636f6d2f636f6e74656e742f43524c2f5347582f4174746573746174696f6e5265706f72745369676e696e6743412e63726c300d06092a864886f70d01010b050003820181006708b61b5c2bd215473e2b46af99284fbb939d3f3b152c996f1a6af3b329bd220b1d3b610f6bce2e6753bded304db21912f385256216cfcba456bd96940be892f5690c260d1ef84f1606040222e5fe08e5326808212a447cfdd64a46e94bf29f6b4b9a721d25b3c4e2f62f58baed5d77c505248f0f801f9fbfb7fd752080095cee80938b339f6dbb4e165600e20e4a718812d49d9901e310a9b51d66c79909c6996599fae6d76a79ef145d9943bf1d3e35d3b42d1fb9a45cbe8ee334c166eee7d32fcdc9935db8ec8bb1d8eb3779dd8ab92b6e387f0147450f1e381d08581fb83df33b15e000a59be57ea94a3a52dc64bdaec959b3464c91e725bbdaea3d99e857e380a23c9d9fb1ef58e9e42d71f12130f9261d7234d6c37e2b03dba40dfdfb13ac4ad8e13fd3756356b6b50015a3ec9580b815d87c2cef715cd28df00bbf2a3c403ebf6691b3f05edd9143803ca085cff57e053eec2f8fea46ea778a68c9be885bc28225bc5f309be4a2b74d3a03945319dd3c7122fed6ff53bb8b8cb3a03c"; - } - - // The extracted RSA modulus of the leaf x509 signing certificate - function signingMod() public pure override returns (bytes memory) { - return - hex"9F3C647EB5773CBB512D2732C0D7415EBB55A0FA9EDE2E649199E6821DB910D53177370977466A6A5E4786CCD2DDEBD4149D6A2F6325529DD10CC98737B0779C1A07E29C47A1AE004948476C489F45A5A15D7AC8ECC6ACC645ADB43D87679DF59C093BC5A2E9696C5478541B979E754B573914BE55D32FF4C09DDF27219934CD990527B3F92ED78FBF29246ABECB71240EF39C2D7107B447545A7FFB10EB060A68A98580219E36910952683892D6A5E2A80803193E407531404E36B315623799AA825074409754A2DFE8F5AFD5FE631E1FC2AF3808906F28A790D9DD9FE060939B125790C5805D037DF56A99531B96DE69DE33ED226CC1207D1042B5C9AB7F404FC711C0FE4769FB9578B1DC0EC469EA1A25E0FF9914886EF2699B235BB4847DD6FF40B606E6170793C2FB98B314587F9CFD257362DFEAB10B3BD2D97673A1A4BD44C453AAF47FC1F2D3D0F384F74A06F89C089F0DA6CDB7FCEEE8C9821A8E54F25C0416D18C46839A5F8012FBDD3DC74D256279ADC2C0D55AFF6F0622425D1B"; - } - - // The extracted RSA exponent of the leaf x509 signing certificate - function signingExp() public pure override returns (bytes memory) { - return hex"010001"; - } - - // The expected MRENCLAVE value in this specific report - function mrenclave() public pure override returns (bytes32) { - return hex"8eb70e76a34bf6cbf9deed7f467b4888cc187f1f1f34cce2d11ca54014149a35"; - } - - // The expected MRSIGNER value in this specific report - function mrsigner() public pure override returns (bytes32) { - return hex"83d719e77deaca1470f6baf62a4d774303c899db69020f9c70ee1dfc08c7ce9e"; - } - - // The expected payload value in this specific report - function payload() public pure override returns (bytes memory) { - // This is a hex-encoded 48 byte BLS public key - return - hex"04a55b152177219971a93a64aafc2d61baeaf86526963caa260e71efa2b865527e0307d7bda85312dd6ff23bcc88f2bf228da6295239f72c31b686c48b7b69cdfd"; - } -} - -contract Guardian2RaveEvidence is MockEvidence { - function report() public pure override returns (bytes memory) { - // Report is inputted as abi-encoded JSON values - return abi.encode( - "209759971368149731737954685751527072004", - "2023-10-16T20:17:08.742105", - "4", - "EbrM6X6YCH3brjPXT23gVh/I2EG5sVfHYh+S54fb0rrAqVRTiRTOSfLsWSVTZc8wrazGG7oooGoMU7Gj5TEhspNWPNBkpcmwf+3WZYsuncw6eX6Uijk+PzPp3dBQSebHsOEQYDRxGeFuWowvkTo2Z5HTavyoRIrSupBTqDE78HA=", - "https://security-center.intel.com", - "[\"INTEL-SA-00334\",\"INTEL-SA-00615\"]", - "SW_HARDENING_NEEDED", - // Already Base64 decoded off-chain - hex"02000100ac0c00000d000d000000000042616c98d53c9712639447c9b0e7003f0000000000000000000000000000000015150b07ff800e000000000000000000000000000000000000000000000000000000000000000000000000000000000005000000000000001f000000000000008eb70e76a34bf6cbf9deed7f467b4888cc187f1f1f34cce2d11ca54014149a35000000000000000000000000000000000000000000000000000000000000000083d719e77deaca1470f6baf62a4d774303c899db69020f9c70ee1dfc08c7ce9e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bc3029f55f939dfad86a268c340aeba8d87daaa3fdc204a0ca36c839aaf0f26c0000000000000000000000000000000000000000000000000000000000000000" - ); - } - - // The leaf x509 signing certificate's signature over the report - function sig() public pure override returns (bytes memory) { - // base64 decoded signature as hex - return - hex"77d614e10b4f29730c14681ea0808758c22f3ffd833020fcd572dc445ca9abd2ea3e2abdcfd5a04f0975202c5f8c17812a5701346d8f75427b16455da264673e02bedb15d06945ab566d39788e586b73a0259f024a68a27b1fa40964f0b695f3394a5cd3a7af283447f5ff8adccf8091640086de1067cf85fb8ee5db5073bb6894478a9a8bee8292bcb839a10529d82300f3c9cbd548279eae92809f99d0fd6dd7280fe1a6b250d5c1e5219afa7032c4771b393d7fb0269027184013cc6bec4ec40a6699bdc967d67c57035c12f129d59559b98c7f6588aa3658bcf3542a221941ee91b100b80ca895b19464b5570537573ddb0426a09a88b2eca50875809b0e"; - } - - // The leaf x509 signing certificate used to sign the report - function signingCert() public pure override returns (bytes memory) { - return - hex"308204a130820309a003020102020900d107765d32a3b096300d06092a864886f70d01010b0500307e310b3009060355040613025553310b300906035504080c0243413114301206035504070c0b53616e746120436c617261311a3018060355040a0c11496e74656c20436f72706f726174696f6e3130302e06035504030c27496e74656c20534758204174746573746174696f6e205265706f7274205369676e696e67204341301e170d3136313132323039333635385a170d3236313132303039333635385a307b310b3009060355040613025553310b300906035504080c0243413114301206035504070c0b53616e746120436c617261311a3018060355040a0c11496e74656c20436f72706f726174696f6e312d302b06035504030c24496e74656c20534758204174746573746174696f6e205265706f7274205369676e696e6730820122300d06092a864886f70d01010105000382010f003082010a0282010100a97a2de0e66ea6147c9ee745ac0162686c7192099afc4b3f040fad6de093511d74e802f510d716038157dcaf84f4104bd3fed7e6b8f99c8817fd1ff5b9b864296c3d81fa8f1b729e02d21d72ffee4ced725efe74bea68fbc4d4244286fcdd4bf64406a439a15bcb4cf67754489c423972b4a80df5c2e7c5bc2dbaf2d42bb7b244f7c95bf92c75d3b33fc5410678a89589d1083da3acc459f2704cd99598c275e7c1878e00757e5bdb4e840226c11c0a17ff79c80b15c1ddb5af21cc2417061fbd2a2da819ed3b72b7efaa3bfebe2805c9b8ac19aa346512d484cfc81941e15f55881cc127e8f7aa12300cd5afb5742fa1d20cb467a5beb1c666cf76a368978b50203010001a381a43081a1301f0603551d2304183016801478437b76a67ebcd0af7e4237eb357c3b8701513c300e0603551d0f0101ff0404030206c0300c0603551d130101ff0402300030600603551d1f045930573055a053a051864f687474703a2f2f7472757374656473657276696365732e696e74656c2e636f6d2f636f6e74656e742f43524c2f5347582f4174746573746174696f6e5265706f72745369676e696e6743412e63726c300d06092a864886f70d01010b050003820181006708b61b5c2bd215473e2b46af99284fbb939d3f3b152c996f1a6af3b329bd220b1d3b610f6bce2e6753bded304db21912f385256216cfcba456bd96940be892f5690c260d1ef84f1606040222e5fe08e5326808212a447cfdd64a46e94bf29f6b4b9a721d25b3c4e2f62f58baed5d77c505248f0f801f9fbfb7fd752080095cee80938b339f6dbb4e165600e20e4a718812d49d9901e310a9b51d66c79909c6996599fae6d76a79ef145d9943bf1d3e35d3b42d1fb9a45cbe8ee334c166eee7d32fcdc9935db8ec8bb1d8eb3779dd8ab92b6e387f0147450f1e381d08581fb83df33b15e000a59be57ea94a3a52dc64bdaec959b3464c91e725bbdaea3d99e857e380a23c9d9fb1ef58e9e42d71f12130f9261d7234d6c37e2b03dba40dfdfb13ac4ad8e13fd3756356b6b50015a3ec9580b815d87c2cef715cd28df00bbf2a3c403ebf6691b3f05edd9143803ca085cff57e053eec2f8fea46ea778a68c9be885bc28225bc5f309be4a2b74d3a03945319dd3c7122fed6ff53bb8b8cb3a03c"; - } - - // The extracted RSA modulus of the leaf x509 signing certificate - function signingMod() public pure override returns (bytes memory) { - return - hex"9F3C647EB5773CBB512D2732C0D7415EBB55A0FA9EDE2E649199E6821DB910D53177370977466A6A5E4786CCD2DDEBD4149D6A2F6325529DD10CC98737B0779C1A07E29C47A1AE004948476C489F45A5A15D7AC8ECC6ACC645ADB43D87679DF59C093BC5A2E9696C5478541B979E754B573914BE55D32FF4C09DDF27219934CD990527B3F92ED78FBF29246ABECB71240EF39C2D7107B447545A7FFB10EB060A68A98580219E36910952683892D6A5E2A80803193E407531404E36B315623799AA825074409754A2DFE8F5AFD5FE631E1FC2AF3808906F28A790D9DD9FE060939B125790C5805D037DF56A99531B96DE69DE33ED226CC1207D1042B5C9AB7F404FC711C0FE4769FB9578B1DC0EC469EA1A25E0FF9914886EF2699B235BB4847DD6FF40B606E6170793C2FB98B314587F9CFD257362DFEAB10B3BD2D97673A1A4BD44C453AAF47FC1F2D3D0F384F74A06F89C089F0DA6CDB7FCEEE8C9821A8E54F25C0416D18C46839A5F8012FBDD3DC74D256279ADC2C0D55AFF6F0622425D1B"; - } - - // The extracted RSA exponent of the leaf x509 signing certificate - function signingExp() public pure override returns (bytes memory) { - return hex"010001"; - } - - // The expected MRENCLAVE value in this specific report - function mrenclave() public pure override returns (bytes32) { - return hex"8eb70e76a34bf6cbf9deed7f467b4888cc187f1f1f34cce2d11ca54014149a35"; - } - - // The expected MRSIGNER value in this specific report - function mrsigner() public pure override returns (bytes32) { - return hex"83d719e77deaca1470f6baf62a4d774303c899db69020f9c70ee1dfc08c7ce9e"; - } - - // The expected payload value in this specific report - function payload() public pure override returns (bytes memory) { - // This is a hex-encoded 48 byte BLS public key - return - hex"04f050c3ce5d575600af388f41876e2962499a97bc8fcfa4a12adf7e4a486a3be9a1db0efd899c09723f83fe490e8215fd596a5f03c819e28a8b95f3cce6238613"; - } -} - -contract Guardian1RaveEvidence is MockEvidence { - function report() public pure override returns (bytes memory) { - // Report is inputted as abi-encoded JSON values - return abi.encode( - "171541400247265784450028677784105405930", - "2023-10-16T20:13:06.744812", - "4", - "EbrM6X6YCH3brjPXT23gVh/I2EG5sVfHYh+S54fb0rrAqVRTiRTOSfLsWSVTZc8wrazGG7oooGoMU7Gj5TEhspNWPNBkpcmwf+3WZYsuncw6eX6Uijk+PzPp3dBQSebHsOEQYDRxGeFuWowvkTo2Z5HTavyoRIrSupBTqDE78HA=", - "https://security-center.intel.com", - "[\"INTEL-SA-00334\",\"INTEL-SA-00615\"]", - "SW_HARDENING_NEEDED", - // Already Base64 decoded off-chain - hex"02000100ac0c00000d000d000000000042616c98d53c9712639447c9b0e7003f0000000000000000000000000000000015150b07ff800e000000000000000000000000000000000000000000000000000000000000000000000000000000000005000000000000001f000000000000008eb70e76a34bf6cbf9deed7f467b4888cc187f1f1f34cce2d11ca54014149a35000000000000000000000000000000000000000000000000000000000000000083d719e77deaca1470f6baf62a4d774303c899db69020f9c70ee1dfc08c7ce9e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003af0644b0725449c3def3104fd7428c3ea005f4607e13453d3c05f3aac07b600000000000000000000000000000000000000000000000000000000000000000" - ); - } - - // The leaf x509 signing certificate's signature over the report - function sig() public pure override returns (bytes memory) { - // base64 decoded signature as hex - return - hex"6cc5a3354c3504677252a3ee19a9d4c64eb8e8ed2bcdd8a7fcfeee88eb8214c0975730b03aeec9b1f56e7cd37030da73b63c8fefb85de1fd2ae70f4d485db8228c76c6dc5da2ce5458c172852d2faec9cca97a1ef4cc19280b84b841e05a7ee33207db18496a3fb515f978ed161d4b7e4c585e76641605be2c31418e04ac35686fa0841b3680d24dac35d8edbfa4c7549b712830b1c0064ae4c0463428ebd0ee833f341fcb2125e9c06d9e67d41f2dc3afe26b1e81d5dbaed1eab6a656e40b9188206f8fdc2745d90db2ebcb671ee44932b9ca7f607c8107bd0c96689bd6aaf9dcdd03afcb433925cacf994527121b79a425a32a86984af5434005b8f422faaa"; - } - - // The leaf x509 signing certificate used to sign the report - function signingCert() public pure override returns (bytes memory) { - return - hex"308204a130820309a003020102020900d107765d32a3b096300d06092a864886f70d01010b0500307e310b3009060355040613025553310b300906035504080c0243413114301206035504070c0b53616e746120436c617261311a3018060355040a0c11496e74656c20436f72706f726174696f6e3130302e06035504030c27496e74656c20534758204174746573746174696f6e205265706f7274205369676e696e67204341301e170d3136313132323039333635385a170d3236313132303039333635385a307b310b3009060355040613025553310b300906035504080c0243413114301206035504070c0b53616e746120436c617261311a3018060355040a0c11496e74656c20436f72706f726174696f6e312d302b06035504030c24496e74656c20534758204174746573746174696f6e205265706f7274205369676e696e6730820122300d06092a864886f70d01010105000382010f003082010a0282010100a97a2de0e66ea6147c9ee745ac0162686c7192099afc4b3f040fad6de093511d74e802f510d716038157dcaf84f4104bd3fed7e6b8f99c8817fd1ff5b9b864296c3d81fa8f1b729e02d21d72ffee4ced725efe74bea68fbc4d4244286fcdd4bf64406a439a15bcb4cf67754489c423972b4a80df5c2e7c5bc2dbaf2d42bb7b244f7c95bf92c75d3b33fc5410678a89589d1083da3acc459f2704cd99598c275e7c1878e00757e5bdb4e840226c11c0a17ff79c80b15c1ddb5af21cc2417061fbd2a2da819ed3b72b7efaa3bfebe2805c9b8ac19aa346512d484cfc81941e15f55881cc127e8f7aa12300cd5afb5742fa1d20cb467a5beb1c666cf76a368978b50203010001a381a43081a1301f0603551d2304183016801478437b76a67ebcd0af7e4237eb357c3b8701513c300e0603551d0f0101ff0404030206c0300c0603551d130101ff0402300030600603551d1f045930573055a053a051864f687474703a2f2f7472757374656473657276696365732e696e74656c2e636f6d2f636f6e74656e742f43524c2f5347582f4174746573746174696f6e5265706f72745369676e696e6743412e63726c300d06092a864886f70d01010b050003820181006708b61b5c2bd215473e2b46af99284fbb939d3f3b152c996f1a6af3b329bd220b1d3b610f6bce2e6753bded304db21912f385256216cfcba456bd96940be892f5690c260d1ef84f1606040222e5fe08e5326808212a447cfdd64a46e94bf29f6b4b9a721d25b3c4e2f62f58baed5d77c505248f0f801f9fbfb7fd752080095cee80938b339f6dbb4e165600e20e4a718812d49d9901e310a9b51d66c79909c6996599fae6d76a79ef145d9943bf1d3e35d3b42d1fb9a45cbe8ee334c166eee7d32fcdc9935db8ec8bb1d8eb3779dd8ab92b6e387f0147450f1e381d08581fb83df33b15e000a59be57ea94a3a52dc64bdaec959b3464c91e725bbdaea3d99e857e380a23c9d9fb1ef58e9e42d71f12130f9261d7234d6c37e2b03dba40dfdfb13ac4ad8e13fd3756356b6b50015a3ec9580b815d87c2cef715cd28df00bbf2a3c403ebf6691b3f05edd9143803ca085cff57e053eec2f8fea46ea778a68c9be885bc28225bc5f309be4a2b74d3a03945319dd3c7122fed6ff53bb8b8cb3a03c"; - } - - // The extracted RSA modulus of the leaf x509 signing certificate - function signingMod() public pure override returns (bytes memory) { - return - hex"9F3C647EB5773CBB512D2732C0D7415EBB55A0FA9EDE2E649199E6821DB910D53177370977466A6A5E4786CCD2DDEBD4149D6A2F6325529DD10CC98737B0779C1A07E29C47A1AE004948476C489F45A5A15D7AC8ECC6ACC645ADB43D87679DF59C093BC5A2E9696C5478541B979E754B573914BE55D32FF4C09DDF27219934CD990527B3F92ED78FBF29246ABECB71240EF39C2D7107B447545A7FFB10EB060A68A98580219E36910952683892D6A5E2A80803193E407531404E36B315623799AA825074409754A2DFE8F5AFD5FE631E1FC2AF3808906F28A790D9DD9FE060939B125790C5805D037DF56A99531B96DE69DE33ED226CC1207D1042B5C9AB7F404FC711C0FE4769FB9578B1DC0EC469EA1A25E0FF9914886EF2699B235BB4847DD6FF40B606E6170793C2FB98B314587F9CFD257362DFEAB10B3BD2D97673A1A4BD44C453AAF47FC1F2D3D0F384F74A06F89C089F0DA6CDB7FCEEE8C9821A8E54F25C0416D18C46839A5F8012FBDD3DC74D256279ADC2C0D55AFF6F0622425D1B"; - } - - // The extracted RSA exponent of the leaf x509 signing certificate - function signingExp() public pure override returns (bytes memory) { - return hex"010001"; - } - - // The expected MRENCLAVE value in this specific report - function mrenclave() public pure override returns (bytes32) { - return hex"8eb70e76a34bf6cbf9deed7f467b4888cc187f1f1f34cce2d11ca54014149a35"; - } - - // The expected MRSIGNER value in this specific report - function mrsigner() public pure override returns (bytes32) { - return hex"83d719e77deaca1470f6baf62a4d774303c899db69020f9c70ee1dfc08c7ce9e"; - } - - // The expected payload value in this specific report - function payload() public pure override returns (bytes memory) { - // This is a hex-encoded 48 byte BLS public key - return - hex"04caf1f9cd82a1284626d405d285250fd6c4f58c469fda05d7fd4f29318aae38e7ccc6f4eaced74d3e2aa3fc0576093860d3045263c4183d694a39911ee9031c73"; - } -} diff --git a/mainnet-contracts/test/helpers/IntegrationTestHelper.sol b/mainnet-contracts/test/helpers/IntegrationTestHelper.sol index 6d3b65db..f5132daa 100644 --- a/mainnet-contracts/test/helpers/IntegrationTestHelper.sol +++ b/mainnet-contracts/test/helpers/IntegrationTestHelper.sol @@ -9,8 +9,8 @@ import { PufferProtocol } from "../../src/PufferProtocol.sol"; import { PufferModuleManager } from "../../src/PufferModuleManager.sol"; import { UpgradeableBeacon } from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; import { DeployEverything } from "script/DeployEverything.s.sol"; -import { IEnclaveVerifier } from "../../src/interface/IEnclaveVerifier.sol"; import { AccessManager } from "@openzeppelin/contracts/access/manager/AccessManager.sol"; +import { IWorkloadVerifier } from "@automata-network/automata-tee-workload-measurement/interfaces/IWorkloadVerifier.sol"; contract IntegrationTestHelper is Test { address DAO = 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; @@ -21,7 +21,8 @@ contract IntegrationTestHelper is Test { GuardianModule public guardianModule; AccessManager public accessManager; - IEnclaveVerifier public verifier; + + IWorkloadVerifier public verifier; bytes32 PUFFER_MODULE_0 = bytes32("PUFFER_MODULE_0"); address PAYMASTER = 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; @@ -55,8 +56,8 @@ contract IntegrationTestHelper is Test { vm.label(address(pufferProtocol), "PufferProtocol"); accessManager = AccessManager(pufferDeployment.accessManager); vm.label(address(accessManager), "AccessManager"); - verifier = IEnclaveVerifier(pufferDeployment.enclaveVerifier); - vm.label(address(verifier), "EnclaveVerifier"); + verifier = IWorkloadVerifier(pufferDeployment.workloadVerifier); + vm.label(address(verifier), "WorkloadVerifier"); guardianModule = GuardianModule(payable(pufferDeployment.guardianModule)); vm.label(address(guardianModule), "GuardianModule"); beacon = UpgradeableBeacon(pufferDeployment.beacon); diff --git a/mainnet-contracts/test/helpers/UnitTestHelper.sol b/mainnet-contracts/test/helpers/UnitTestHelper.sol index 73a3d3da..7de1cea9 100644 --- a/mainnet-contracts/test/helpers/UnitTestHelper.sol +++ b/mainnet-contracts/test/helpers/UnitTestHelper.sol @@ -9,13 +9,11 @@ import { PufferProtocol } from "../../src/PufferProtocol.sol"; import { PufferModuleManager } from "../../src/PufferModuleManager.sol"; import { AVSContractsRegistry } from "../../src/AVSContractsRegistry.sol"; import { RestakingOperatorController } from "../../src/RestakingOperatorController.sol"; -import { RaveEvidence } from "../../src/struct/RaveEvidence.sol"; import { IGuardianModule } from "../../src/interface/IGuardianModule.sol"; import { UpgradeableBeacon } from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; import { DeployEverything } from "../../script/DeployEverything.s.sol"; import { PufferProtocolDeployment, BridgingDeployment } from "../../script/DeploymentStructs.sol"; -import { IEnclaveVerifier } from "../../src/interface/IEnclaveVerifier.sol"; -import { Guardian1RaveEvidence, Guardian2RaveEvidence, Guardian3RaveEvidence } from "./GuardiansRaveEvidence.sol"; +import { IWorkloadVerifier } from "@automata-network/automata-tee-workload-measurement/interfaces/IWorkloadVerifier.sol"; import { AccessManager } from "@openzeppelin/contracts/access/manager/AccessManager.sol"; import { Permit } from "../../src/structs/Permit.sol"; import { PufferDepositor } from "../../src/PufferDepositor.sol"; @@ -25,12 +23,9 @@ import { IWETH } from "../../src/interface/Other/IWETH.sol"; import { ValidatorTicket } from "../../src/ValidatorTicket.sol"; import { ValidatorTicketPricer } from "../../src/ValidatorTicketPricer.sol"; import { OperationsCoordinator } from "../../src/OperationsCoordinator.sol"; -// import { xPufETH } from "src/l2/xPufETH.sol"; -// import { XERC20Lockbox } from "src/XERC20Lockbox.sol"; import { L1RewardManager } from "src/L1RewardManager.sol"; import { PufferRevenueDepositor } from "src/PufferRevenueDepositor.sol"; import { L2RewardManager } from "l2-contracts/src/L2RewardManager.sol"; -// import { ConnextMock } from "../mocks/ConnextMock.sol"; import { pufETHAdapter } from "partners-layerzero/contracts/pufETHAdapter.sol"; import { pufETH } from "partners-layerzero/contracts/pufETH.sol"; import { @@ -101,7 +96,7 @@ contract UnitTestHelper is Test, BaseScript { GuardianModule public guardianModule; AccessManager public accessManager; - IEnclaveVerifier public verifier; + IWorkloadVerifier public verifier; OperationsCoordinator public operationsCoordinator; AVSContractsRegistry public avsContractsRegistry; RestakingOperatorController public restakingOperatorController; @@ -210,7 +205,7 @@ contract UnitTestHelper is Test, BaseScript { pufferProtocol = PufferProtocol(payable(pufferDeployment.pufferProtocol)); accessManager = AccessManager(pufferDeployment.accessManager); timelock = pufferDeployment.timelock; - verifier = IEnclaveVerifier(pufferDeployment.enclaveVerifier); + verifier = IWorkloadVerifier(pufferDeployment.workloadVerifier); guardianModule = GuardianModule(payable(pufferDeployment.guardianModule)); beacon = UpgradeableBeacon(pufferDeployment.beacon); pufferModuleManager = PufferModuleManager(payable(pufferDeployment.moduleManager)); @@ -258,9 +253,6 @@ contract UnitTestHelper is Test, BaseScript { assertEq(guardianModule.getMrenclave(), guardian1Rave.mrenclave(), "mrenclave"); assertEq(guardianModule.getMrsigner(), guardian1Rave.mrsigner(), "mrsigner"); - // Add a valid certificate to verifier - verifier = guardianModule.ENCLAVE_VERIFIER(); - verifier.addLeafX509(guardian1Rave.signingCert()); require(keccak256(guardian1EnclavePubKey) == keccak256(guardian1Rave.payload()), "pubkeys don't match"); diff --git a/mainnet-contracts/test/mocks/WorkloadVerifierMock.sol b/mainnet-contracts/test/mocks/WorkloadVerifierMock.sol new file mode 100644 index 00000000..c445695e --- /dev/null +++ b/mainnet-contracts/test/mocks/WorkloadVerifierMock.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.8.0 <0.9.0; + +import { TEEType, TeeReportType, CloudType, WorkloadCollaterals } from "@automata-network/automata-tee-workload-measurement/interfaces/IWorkloadVerifier.sol"; + +contract WorkloadVerifierMock { + function verifyAttestationAndGetMeasurementHash( + TEEType teeType, + TeeReportType teeReportType, + CloudType cloudType, + bytes calldata _teeAttestationReport, + WorkloadCollaterals calldata _workloadReport + ) external payable returns (bytes memory teeOutput, bytes32 measurementHash, bytes memory tpmExtraData) { + // TODO + } +} diff --git a/mainnet-contracts/test/unit/EnclaveVerifier.t.sol b/mainnet-contracts/test/unit/EnclaveVerifier.t.sol deleted file mode 100644 index c64573a4..00000000 --- a/mainnet-contracts/test/unit/EnclaveVerifier.t.sol +++ /dev/null @@ -1,106 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity >=0.8.0 <0.9.0; - -import { Test } from "forge-std/Test.sol"; -import { EnclaveVerifier } from "../../src/EnclaveVerifier.sol"; -import { IEnclaveVerifier } from "../../src/interface/IEnclaveVerifier.sol"; -import { RaveEvidence } from "../../src/struct/RaveEvidence.sol"; -import { MockEvidence } from "rave-test/mocks/MockEvidence.sol"; -import { UnitTestHelper } from "../helpers/UnitTestHelper.sol"; -import { - Guardian1RaveEvidence, Guardian2RaveEvidence, Guardian3RaveEvidence -} from "../helpers/GuardiansRaveEvidence.sol"; - -contract EnclaveVerifierTest is UnitTestHelper { - // DER encoded bytes of the signed Intel Leaf Signing x509 Certificate (including the header and signature) - // Copied from "lib/rave/test/X509Verifier.t.sol" - bytes public validLeafX509Certificate = - hex"308204a130820309a003020102020900d107765d32a3b096300d06092a864886f70d01010b0500307e310b3009060355040613025553310b300906035504080c0243413114301206035504070c0b53616e746120436c617261311a3018060355040a0c11496e74656c20436f72706f726174696f6e3130302e06035504030c27496e74656c20534758204174746573746174696f6e205265706f7274205369676e696e67204341301e170d3136313132323039333635385a170d3236313132303039333635385a307b310b3009060355040613025553310b300906035504080c0243413114301206035504070c0b53616e746120436c617261311a3018060355040a0c11496e74656c20436f72706f726174696f6e312d302b06035504030c24496e74656c20534758204174746573746174696f6e205265706f7274205369676e696e6730820122300d06092a864886f70d01010105000382010f003082010a0282010100a97a2de0e66ea6147c9ee745ac0162686c7192099afc4b3f040fad6de093511d74e802f510d716038157dcaf84f4104bd3fed7e6b8f99c8817fd1ff5b9b864296c3d81fa8f1b729e02d21d72ffee4ced725efe74bea68fbc4d4244286fcdd4bf64406a439a15bcb4cf67754489c423972b4a80df5c2e7c5bc2dbaf2d42bb7b244f7c95bf92c75d3b33fc5410678a89589d1083da3acc459f2704cd99598c275e7c1878e00757e5bdb4e840226c11c0a17ff79c80b15c1ddb5af21cc2417061fbd2a2da819ed3b72b7efaa3bfebe2805c9b8ac19aa346512d484cfc81941e15f55881cc127e8f7aa12300cd5afb5742fa1d20cb467a5beb1c666cf76a368978b50203010001a381a43081a1301f0603551d2304183016801478437b76a67ebcd0af7e4237eb357c3b8701513c300e0603551d0f0101ff0404030206c0300c0603551d130101ff0402300030600603551d1f045930573055a053a051864f687474703a2f2f7472757374656473657276696365732e696e74656c2e636f6d2f636f6e74656e742f43524c2f5347582f4174746573746174696f6e5265706f72745369676e696e6743412e63726c300d06092a864886f70d01010b050003820181006708b61b5c2bd215473e2b46af99284fbb939d3f3b152c996f1a6af3b329bd220b1d3b610f6bce2e6753bded304db21912f385256216cfcba456bd96940be892f5690c260d1ef84f1606040222e5fe08e5326808212a447cfdd64a46e94bf29f6b4b9a721d25b3c4e2f62f58baed5d77c505248f0f801f9fbfb7fd752080095cee80938b339f6dbb4e165600e20e4a718812d49d9901e310a9b51d66c79909c6996599fae6d76a79ef145d9943bf1d3e35d3b42d1fb9a45cbe8ee334c166eee7d32fcdc9935db8ec8bb1d8eb3779dd8ab92b6e387f0147450f1e381d08581fb83df33b15e000a59be57ea94a3a52dc64bdaec959b3464c91e725bbdaea3d99e857e380a23c9d9fb1ef58e9e42d71f12130f9261d7234d6c37e2b03dba40dfdfb13ac4ad8e13fd3756356b6b50015a3ec9580b815d87c2cef715cd28df00bbf2a3c403ebf6691b3f05edd9143803ca085cff57e053eec2f8fea46ea778a68c9be885bc28225bc5f309be4a2b74d3a03945319dd3c7122fed6ff53bb8b8cb3a03c"; - - // Test setup - function testSetup() public view { - EnclaveVerifier.RSAPubKey memory intelPubKey = verifier.getIntelRootCAPubKey(); - assertEq( - intelPubKey.modulus, - hex"9F3C647EB5773CBB512D2732C0D7415EBB55A0FA9EDE2E649199E6821DB910D53177370977466A6A5E4786CCD2DDEBD4149D6A2F6325529DD10CC98737B0779C1A07E29C47A1AE004948476C489F45A5A15D7AC8ECC6ACC645ADB43D87679DF59C093BC5A2E9696C5478541B979E754B573914BE55D32FF4C09DDF27219934CD990527B3F92ED78FBF29246ABECB71240EF39C2D7107B447545A7FFB10EB060A68A98580219E36910952683892D6A5E2A80803193E407531404E36B315623799AA825074409754A2DFE8F5AFD5FE631E1FC2AF3808906F28A790D9DD9FE060939B125790C5805D037DF56A99531B96DE69DE33ED226CC1207D1042B5C9AB7F404FC711C0FE4769FB9578B1DC0EC469EA1A25E0FF9914886EF2699B235BB4847DD6FF40B606E6170793C2FB98B314587F9CFD257362DFEAB10B3BD2D97673A1A4BD44C453AAF47FC1F2D3D0F384F74A06F89C089F0DA6CDB7FCEEE8C9821A8E54F25C0416D18C46839A5F8012FBDD3DC74D256279ADC2C0D55AFF6F0622425D1B", - "intel modulus" - ); - assertEq(intelPubKey.exponent, hex"010001", "intel exponent"); - } - - // Test add leaf - function testAddLeafX509() public { - vm.expectEmit(true, true, true, true); - emit IEnclaveVerifier.AddedPubKey(keccak256(validLeafX509Certificate)); - verifier.addLeafX509(validLeafX509Certificate); - } - - // Test remove leaf - function testRemoveLeafX509() public { - testAddLeafX509(); - bytes32 hashedCertificate = keccak256(validLeafX509Certificate); - - vm.startPrank(DAO); - vm.expectEmit(true, true, true, true); - emit IEnclaveVerifier.RemovedPubKey(hashedCertificate); - EnclaveVerifier(address(verifier)).removeLeafX509(hashedCertificate); - } - - function testRaveEvidence1() public { - _verifyValidatorPubKey(new Guardian1RaveEvidence()); - } - - function testRaveEvidence2() public { - _verifyValidatorPubKey(new Guardian2RaveEvidence()); - } - - function testRaveEvidence3() public { - _verifyValidatorPubKey(new Guardian3RaveEvidence()); - } - - function testVerifyingStaleEvidence() public { - Guardian3RaveEvidence raveEvidence = new Guardian3RaveEvidence(); - - vm.roll(5000); - - RaveEvidence memory evidence = RaveEvidence({ - report: raveEvidence.report(), - signature: raveEvidence.sig(), - leafX509CertDigest: keccak256(raveEvidence.signingCert()) - }); - - bytes32 mrenclave = raveEvidence.mrenclave(); - bytes32 mrsigner = raveEvidence.mrsigner(); - bytes32 commitment = keccak256(raveEvidence.payload()); - - vm.expectRevert(IEnclaveVerifier.StaleEvidence.selector); - verifier.verifyEvidence({ - blockNumber: 0, - evidence: evidence, - raveCommitment: commitment, - mrenclave: mrenclave, - mrsigner: mrsigner - }); - } - - // Verify rave evidence - function _verifyValidatorPubKey(MockEvidence raveEvidence) public { - verifier.addLeafX509(raveEvidence.signingCert()); - - RaveEvidence memory evidence = RaveEvidence({ - report: raveEvidence.report(), - signature: raveEvidence.sig(), - leafX509CertDigest: keccak256(raveEvidence.signingCert()) - }); - - bool success = verifier.verifyEvidence({ - blockNumber: 0, - evidence: evidence, - raveCommitment: keccak256(raveEvidence.payload()), - mrenclave: raveEvidence.mrenclave(), - mrsigner: raveEvidence.mrsigner() - }); - - assertTrue(success, "should verify rave"); - } -} diff --git a/mainnet-contracts/test/unit/GuardianModule.t.sol b/mainnet-contracts/test/unit/GuardianModule.t.sol index c47f6a56..f056e67f 100644 --- a/mainnet-contracts/test/unit/GuardianModule.t.sol +++ b/mainnet-contracts/test/unit/GuardianModule.t.sol @@ -2,10 +2,7 @@ pragma solidity >=0.8.0 <0.9.0; import { UnitTestHelper } from "../helpers/UnitTestHelper.sol"; -import { RaveEvidence } from "../../src/struct/RaveEvidence.sol"; -import { RaveEvidence } from "../../src/struct/RaveEvidence.sol"; import { IGuardianModule } from "../../src/interface/IGuardianModule.sol"; -import { Guardian2RaveEvidence } from "../helpers/GuardiansRaveEvidence.sol"; import { Unauthorized } from "../../src/Errors.sol"; contract GuardianModuleTest is UnitTestHelper { From e158a72501f66f7e0a6ec4c15a6f987806d0ebc6 Mon Sep 17 00:00:00 2001 From: Eladio Date: Fri, 30 Jan 2026 16:50:33 +0100 Subject: [PATCH 16/51] Adapted tests (WIP) --- .../script/DeployEverything.s.sol | 3 +- .../test/helpers/IntegrationTestHelper.sol | 3 +- .../test/helpers/UnitTestHelper.sol | 104 ++++++++---------- .../test/unit/GuardianModule.t.sol | 47 ++++---- 4 files changed, 74 insertions(+), 83 deletions(-) diff --git a/mainnet-contracts/script/DeployEverything.s.sol b/mainnet-contracts/script/DeployEverything.s.sol index 92319b0d..4eaaffc7 100644 --- a/mainnet-contracts/script/DeployEverything.s.sol +++ b/mainnet-contracts/script/DeployEverything.s.sol @@ -16,6 +16,7 @@ import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy import { GenerateRevenueDepositorCalldata } from "script/AccessManagerMigrations/06_GenerateRevenueDepositorCalldata.s.sol"; import { MockAeraVault } from "test/mocks/MockAeraVault.sol"; +import { IWorkloadVerifier } from "@automata-network/automata-tee-workload-measurement/interfaces/IWorkloadVerifier.sol"; /** * @title Deploy all protocol contracts @@ -45,7 +46,7 @@ contract DeployEverything is BaseScript { deployment.accessManager = puffETHDeployment.accessManager; GuardiansDeployment memory guardiansDeployment = - new DeployGuardians().run(workloadVerifier, AccessManager(puffETHDeployment.accessManager), guardians, threshold); + new DeployGuardians().run(IWorkloadVerifier(workloadVerifier), AccessManager(puffETHDeployment.accessManager), guardians, threshold); address pufferOracle = new DeployPufferOracle().run( puffETHDeployment.accessManager, guardiansDeployment.guardianModule, puffETHDeployment.pufferVault diff --git a/mainnet-contracts/test/helpers/IntegrationTestHelper.sol b/mainnet-contracts/test/helpers/IntegrationTestHelper.sol index f5132daa..6cde8427 100644 --- a/mainnet-contracts/test/helpers/IntegrationTestHelper.sol +++ b/mainnet-contracts/test/helpers/IntegrationTestHelper.sol @@ -26,6 +26,7 @@ contract IntegrationTestHelper is Test { bytes32 PUFFER_MODULE_0 = bytes32("PUFFER_MODULE_0"); address PAYMASTER = 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; + address WORKLOAD_VERIFIER = address(0); //TODO [TDX] Set the address of the workload verifier // custom block number function deployContractsHoodi(uint256 blockNumber) public virtual { @@ -50,7 +51,7 @@ contract IntegrationTestHelper is Test { function _deployAndLabel(address[] memory guardians, uint256 threshold) internal { // Deploy everything with one script (PufferProtocolDeployment memory pufferDeployment,) = - new DeployEverything().run(guardians, threshold, PAYMASTER); + new DeployEverything().run(WORKLOAD_VERIFIER, guardians, threshold, PAYMASTER); pufferProtocol = PufferProtocol(payable(pufferDeployment.pufferProtocol)); vm.label(address(pufferProtocol), "PufferProtocol"); diff --git a/mainnet-contracts/test/helpers/UnitTestHelper.sol b/mainnet-contracts/test/helpers/UnitTestHelper.sol index 7de1cea9..bb6fda38 100644 --- a/mainnet-contracts/test/helpers/UnitTestHelper.sol +++ b/mainnet-contracts/test/helpers/UnitTestHelper.sol @@ -35,6 +35,7 @@ import { ROLE_ID_LOCKBOX } from "../../script/Roles.sol"; import { GenerateSlashingELCalldata } from "../../script/AccessManagerMigrations/07_GenerateSlashingELCalldata.s.sol"; +import { WorkloadVerifierMock } from "../mocks/WorkloadVerifierMock.sol"; contract UnitTestHelper is Test, BaseScript { bytes32 private constant _PERMIT_TYPEHASH = @@ -196,11 +197,13 @@ contract UnitTestHelper is Test, BaseScript { guardians[1] = guardian2; guardians[2] = guardian3; + WorkloadVerifierMock workloadVerifierMock = new WorkloadVerifierMock(); + // Deploy everything with one script PufferProtocolDeployment memory pufferDeployment; BridgingDeployment memory bridgingDeployment; - (pufferDeployment, bridgingDeployment) = new DeployEverything().run(guardians, 1, PAYMASTER); + (pufferDeployment, bridgingDeployment) = new DeployEverything().run(address(workloadVerifierMock), guardians, 1, PAYMASTER); pufferProtocol = PufferProtocol(payable(pufferDeployment.pufferProtocol)); accessManager = AccessManager(pufferDeployment.accessManager); @@ -238,23 +241,7 @@ contract UnitTestHelper is Test, BaseScript { vm.label(address(pufferDepositor), "PufferDepositor"); vm.label(address(pufferProtocol), "PufferProtocol"); - Guardian1RaveEvidence guardian1Rave = new Guardian1RaveEvidence(); - Guardian2RaveEvidence guardian2Rave = new Guardian2RaveEvidence(); - Guardian3RaveEvidence guardian3Rave = new Guardian3RaveEvidence(); - - // mrenclave and mrsigner are the same for all evidences - vm.startPrank(DAO); - vm.expectEmit(true, true, true, true); - emit IGuardianModule.MrEnclaveChanged(bytes32(0), guardian1Rave.mrenclave()); - emit IGuardianModule.MrSignerChanged(bytes32(0), guardian1Rave.mrsigner()); - guardianModule.setGuardianEnclaveMeasurements(guardian1Rave.mrenclave(), guardian1Rave.mrsigner()); - vm.stopPrank(); - - assertEq(guardianModule.getMrenclave(), guardian1Rave.mrenclave(), "mrenclave"); - assertEq(guardianModule.getMrsigner(), guardian1Rave.mrsigner(), "mrsigner"); - - - require(keccak256(guardian1EnclavePubKey) == keccak256(guardian1Rave.payload()), "pubkeys don't match"); + // TODO [TDX] Register Golden Measurement assertEq( blockhash(block.number), @@ -262,47 +249,48 @@ contract UnitTestHelper is Test, BaseScript { "bad blockhash" ); + // TODO [TDX] Update rotateGuardiankey to current impl // Register enclave keys for guardians - vm.startPrank(guardians[0]); - vm.expectEmit(true, true, true, true); - emit IGuardianModule.RotatedGuardianKey(guardians[0], guardian1Enclave, guardian1EnclavePubKey); - guardianModule.rotateGuardianKey( - 0, - guardian1EnclavePubKey, - RaveEvidence({ - report: guardian1Rave.report(), - signature: guardian1Rave.sig(), - leafX509CertDigest: keccak256(guardian1Rave.signingCert()) - }) - ); - vm.stopPrank(); - - vm.startPrank(guardians[1]); - vm.expectEmit(true, true, true, true); - emit IGuardianModule.RotatedGuardianKey(guardians[1], guardian2Enclave, guardian2EnclavePubKey); - guardianModule.rotateGuardianKey( - 0, - guardian2EnclavePubKey, - RaveEvidence({ - report: guardian2Rave.report(), - signature: guardian2Rave.sig(), - leafX509CertDigest: keccak256(guardian2Rave.signingCert()) - }) - ); - vm.stopPrank(); - - vm.startPrank(guardians[2]); - vm.expectEmit(true, true, true, true); - emit IGuardianModule.RotatedGuardianKey(guardians[2], guardian3Enclave, guardian3EnclavePubKey); - guardianModule.rotateGuardianKey( - 0, - guardian3EnclavePubKey, - RaveEvidence({ - report: guardian3Rave.report(), - signature: guardian3Rave.sig(), - leafX509CertDigest: keccak256(guardian3Rave.signingCert()) - }) - ); + // vm.startPrank(guardians[0]); + // vm.expectEmit(true, true, true, true); + // emit IGuardianModule.RotatedGuardianKey(guardians[0], guardian1Enclave, guardian1EnclavePubKey); + // guardianModule.rotateGuardianKey( + // 0, + // guardian1EnclavePubKey, + // RaveEvidence({ + // report: guardian1Rave.report(), + // signature: guardian1Rave.sig(), + // leafX509CertDigest: keccak256(guardian1Rave.signingCert()) + // }) + // ); + // vm.stopPrank(); + + // vm.startPrank(guardians[1]); + // vm.expectEmit(true, true, true, true); + // emit IGuardianModule.RotatedGuardianKey(guardians[1], guardian2Enclave, guardian2EnclavePubKey); + // guardianModule.rotateGuardianKey( + // 0, + // guardian2EnclavePubKey, + // RaveEvidence({ + // report: guardian2Rave.report(), + // signature: guardian2Rave.sig(), + // leafX509CertDigest: keccak256(guardian2Rave.signingCert()) + // }) + // ); + // vm.stopPrank(); + + // vm.startPrank(guardians[2]); + // vm.expectEmit(true, true, true, true); + // emit IGuardianModule.RotatedGuardianKey(guardians[2], guardian3Enclave, guardian3EnclavePubKey); + // guardianModule.rotateGuardianKey( + // 0, + // guardian3EnclavePubKey, + // RaveEvidence({ + // report: guardian3Rave.report(), + // signature: guardian3Rave.sig(), + // leafX509CertDigest: keccak256(guardian3Rave.signingCert()) + // }) + // ); vm.stopPrank(); assertEq(guardianModule.getGuardiansEnclaveAddress(guardians[0]), guardian1Enclave, "bad enclave address1"); diff --git a/mainnet-contracts/test/unit/GuardianModule.t.sol b/mainnet-contracts/test/unit/GuardianModule.t.sol index f056e67f..5affee21 100644 --- a/mainnet-contracts/test/unit/GuardianModule.t.sol +++ b/mainnet-contracts/test/unit/GuardianModule.t.sol @@ -34,20 +34,21 @@ contract GuardianModuleTest is UnitTestHelper { guardianModule.setThreshold(50); } - function test_rotateGuardianKey_from_non_guardian_reverts() public { - RaveEvidence memory evidence; - vm.expectRevert(Unauthorized.selector); - guardianModule.rotateGuardianKey(0, new bytes(55), evidence); - } + // TODO [TDX] Update rotateGuardianKey tests + // function test_rotateGuardianKey_from_non_guardian_reverts() public { + // RaveEvidence memory evidence; + // vm.expectRevert(Unauthorized.selector); + // guardianModule.rotateGuardianKey(0, new bytes(55), evidence); + // } - function test_rotateGuardianKey_to_invalid_pubKey_everts() public { - RaveEvidence memory evidence; + // function test_rotateGuardianKey_to_invalid_pubKey_everts() public { + // RaveEvidence memory evidence; - vm.startPrank(guardian1); + // vm.startPrank(guardian1); - vm.expectRevert(IGuardianModule.InvalidECDSAPubKey.selector); - guardianModule.rotateGuardianKey(0, new bytes(55), evidence); - } + // vm.expectRevert(IGuardianModule.InvalidECDSAPubKey.selector); + // guardianModule.rotateGuardianKey(0, new bytes(55), evidence); + // } function test_addGuardian(address guardian) public assumeEOA(guardian) { vm.startPrank(DAO); @@ -105,21 +106,21 @@ contract GuardianModuleTest is UnitTestHelper { vm.expectRevert(); guardianModule.setThreshold(5); } + // TODO [TDX] Update rotateGuardianKey tests + // function test_rotateGuardianKey_with_invalid_rave_reverts() public { + // Guardian2RaveEvidence guardian2Rave = new Guardian2RaveEvidence(); - function test_rotateGuardianKey_with_invalid_rave_reverts() public { - Guardian2RaveEvidence guardian2Rave = new Guardian2RaveEvidence(); + // vm.startPrank(guardian1); - vm.startPrank(guardian1); + // RaveEvidence memory rave = RaveEvidence({ + // report: guardian2Rave.report(), + // signature: guardian2Rave.sig(), + // leafX509CertDigest: keccak256(guardian2Rave.signingCert()) + // }); - RaveEvidence memory rave = RaveEvidence({ - report: guardian2Rave.report(), - signature: guardian2Rave.sig(), - leafX509CertDigest: keccak256(guardian2Rave.signingCert()) - }); - - vm.expectRevert(IGuardianModule.InvalidRAVE.selector); - guardianModule.rotateGuardianKey(0, guardian3EnclavePubKey, rave); - } + // vm.expectRevert(IGuardianModule.InvalidRAVE.selector); + // guardianModule.rotateGuardianKey(0, guardian3EnclavePubKey, rave); + // } // Invalid signature reverts with unauthorized function test_validateSkipProvisioning_reverts() public { From e406700b46db5e47e1eae82076edb34f729fe324 Mon Sep 17 00:00:00 2001 From: Eladio Date: Mon, 2 Feb 2026 18:07:55 +0100 Subject: [PATCH 17/51] Adapted unit tests and improved verifier mock --- .../script/DeployEverything.s.sol | 5 +- .../script/DeployGuardians.s.sol | 11 +- mainnet-contracts/script/SetupAccess.s.sol | 4 +- .../test/helpers/UnitTestHelper.sol | 141 ++++++++++++------ .../test/mocks/WorkloadVerifierMock.sol | 26 +++- 5 files changed, 127 insertions(+), 60 deletions(-) diff --git a/mainnet-contracts/script/DeployEverything.s.sol b/mainnet-contracts/script/DeployEverything.s.sol index 4eaaffc7..b7845ffd 100644 --- a/mainnet-contracts/script/DeployEverything.s.sol +++ b/mainnet-contracts/script/DeployEverything.s.sol @@ -45,8 +45,9 @@ contract DeployEverything is BaseScript { deployment.weth = puffETHDeployment.weth; deployment.accessManager = puffETHDeployment.accessManager; - GuardiansDeployment memory guardiansDeployment = - new DeployGuardians().run(IWorkloadVerifier(workloadVerifier), AccessManager(puffETHDeployment.accessManager), guardians, threshold); + GuardiansDeployment memory guardiansDeployment = new DeployGuardians().run( + IWorkloadVerifier(workloadVerifier), AccessManager(puffETHDeployment.accessManager), guardians, threshold + ); address pufferOracle = new DeployPufferOracle().run( puffETHDeployment.accessManager, guardiansDeployment.guardianModule, puffETHDeployment.pufferVault diff --git a/mainnet-contracts/script/DeployGuardians.s.sol b/mainnet-contracts/script/DeployGuardians.s.sol index 7961760d..211b8c14 100644 --- a/mainnet-contracts/script/DeployGuardians.s.sol +++ b/mainnet-contracts/script/DeployGuardians.s.sol @@ -9,11 +9,12 @@ import { IWorkloadVerifier } from "@automata-network/automata-tee-workload-measu // forge script script/1_DeployGuardians.s.sol:DeployGuardians --rpc-url=$EPHEMERY_RPC_URL --sig 'run(address, address, address[] calldata, uint256)' "[0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0]" 1 contract DeployGuardians is BaseScript { - function run(IWorkloadVerifier workloadVerifier, AccessManager accessManager, address[] calldata guardians, uint256 threshold) - public - broadcast - returns (GuardiansDeployment memory) - { + function run( + IWorkloadVerifier workloadVerifier, + AccessManager accessManager, + address[] calldata guardians, + uint256 threshold + ) public broadcast returns (GuardiansDeployment memory) { vm.label(address(accessManager), "AccessManager"); GuardianModule module = new GuardianModule(workloadVerifier, guardians, threshold, address(accessManager)); diff --git a/mainnet-contracts/script/SetupAccess.s.sol b/mainnet-contracts/script/SetupAccess.s.sol index 2e8dd45e..84f66220 100644 --- a/mainnet-contracts/script/SetupAccess.s.sol +++ b/mainnet-contracts/script/SetupAccess.s.sol @@ -97,7 +97,7 @@ contract SetupAccess is BaseScript { bytes[] memory coordinatorAccess, bytes[] memory validatorTicketAccess ) internal view returns (bytes[] memory calldatas) { - calldatas = new bytes[](30); + calldatas = new bytes[](29); calldatas[0] = _setupGuardianModuleRoles(); calldatas[1] = rolesCalldatas[0]; calldatas[2] = rolesCalldatas[1]; @@ -267,7 +267,7 @@ contract SetupAccess is BaseScript { } function _setupGuardianModuleRoles() internal view returns (bytes memory) { - bytes4[] memory selectors = new bytes4[](5); + bytes4[] memory selectors = new bytes4[](6); selectors[0] = GuardianModule.registerGoldenMeasurement.selector; selectors[1] = GuardianModule.deregisterGoldenMeasurement.selector; selectors[2] = GuardianModule.addGuardian.selector; diff --git a/mainnet-contracts/test/helpers/UnitTestHelper.sol b/mainnet-contracts/test/helpers/UnitTestHelper.sol index bb6fda38..7e0b8b06 100644 --- a/mainnet-contracts/test/helpers/UnitTestHelper.sol +++ b/mainnet-contracts/test/helpers/UnitTestHelper.sol @@ -13,7 +13,15 @@ import { IGuardianModule } from "../../src/interface/IGuardianModule.sol"; import { UpgradeableBeacon } from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; import { DeployEverything } from "../../script/DeployEverything.s.sol"; import { PufferProtocolDeployment, BridgingDeployment } from "../../script/DeploymentStructs.sol"; -import { IWorkloadVerifier } from "@automata-network/automata-tee-workload-measurement/interfaces/IWorkloadVerifier.sol"; +import { + IWorkloadVerifier, + TEEType, + CloudType, + WorkloadCollaterals +} from "@automata-network/automata-tee-workload-measurement/interfaces/IWorkloadVerifier.sol"; +import { TeeReportType } from "@automata-network/automata-tee-workload-measurement/lib/LibTEE.sol"; +import { MeasureablePcr } from "@automata-network/automata-tpm-attestation/interfaces/ITpmAttestation.sol"; +import { GoldenMeasurementInfo, TdxRegistrationData } from "../../src/struct/GuardianModuleStructs.sol"; import { AccessManager } from "@openzeppelin/contracts/access/manager/AccessManager.sol"; import { Permit } from "../../src/structs/Permit.sol"; import { PufferDepositor } from "../../src/PufferDepositor.sol"; @@ -83,6 +91,9 @@ contract UnitTestHelper is Test, BaseScript { bytes public guardian3EnclavePubKey = hex"04a55b152177219971a93a64aafc2d61baeaf86526963caa260e71efa2b865527e0307d7bda85312dd6ff23bcc88f2bf228da6295239f72c31b686c48b7b69cdfd"; + // TDX attestation test data + bytes public guardian1TdxAttestationReport = hex""; + PufferDepositor public pufferDepositor; PufferVaultV5 public pufferVault; stETHMock public stETH; @@ -203,7 +214,8 @@ contract UnitTestHelper is Test, BaseScript { PufferProtocolDeployment memory pufferDeployment; BridgingDeployment memory bridgingDeployment; - (pufferDeployment, bridgingDeployment) = new DeployEverything().run(address(workloadVerifierMock), guardians, 1, PAYMASTER); + (pufferDeployment, bridgingDeployment) = + new DeployEverything().run(address(workloadVerifierMock), guardians, 1, PAYMASTER); pufferProtocol = PufferProtocol(payable(pufferDeployment.pufferProtocol)); accessManager = AccessManager(pufferDeployment.accessManager); @@ -241,7 +253,31 @@ contract UnitTestHelper is Test, BaseScript { vm.label(address(pufferDepositor), "PufferDepositor"); vm.label(address(pufferProtocol), "PufferProtocol"); - // TODO [TDX] Register Golden Measurement + // Register Golden Measurement for TDX + vm.startPrank(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266); + // Grant DAO role to DAO address + accessManager.grantRole(ROLE_ID_DAO, DAO, 0); + // Set up registerGoldenMeasurement function to require DAO role + bytes4[] memory guardianModuleSelectors = new bytes4[](1); + guardianModuleSelectors[0] = GuardianModule.registerGoldenMeasurement.selector; + accessManager.setTargetFunctionRole(address(guardianModule), guardianModuleSelectors, ROLE_ID_DAO); + vm.stopPrank(); + + // Register a test golden measurement + bytes32 testMeasurementHash = keccak256("test-golden-measurement"); + vm.startPrank(DAO); + guardianModule.registerGoldenMeasurement( + testMeasurementHash, + GoldenMeasurementInfo({ + valid: true, + teeType: TEEType.IntelTDX, + cloudType: CloudType.GCP, + tag: "test-v1.0.0" + }) + ); + + workloadVerifierMock.setMeasurementHash(testMeasurementHash); + vm.stopPrank(); assertEq( blockhash(block.number), @@ -249,50 +285,56 @@ contract UnitTestHelper is Test, BaseScript { "bad blockhash" ); - // TODO [TDX] Update rotateGuardiankey to current impl // Register enclave keys for guardians - // vm.startPrank(guardians[0]); - // vm.expectEmit(true, true, true, true); - // emit IGuardianModule.RotatedGuardianKey(guardians[0], guardian1Enclave, guardian1EnclavePubKey); - // guardianModule.rotateGuardianKey( - // 0, - // guardian1EnclavePubKey, - // RaveEvidence({ - // report: guardian1Rave.report(), - // signature: guardian1Rave.sig(), - // leafX509CertDigest: keccak256(guardian1Rave.signingCert()) - // }) - // ); - // vm.stopPrank(); - - // vm.startPrank(guardians[1]); - // vm.expectEmit(true, true, true, true); - // emit IGuardianModule.RotatedGuardianKey(guardians[1], guardian2Enclave, guardian2EnclavePubKey); - // guardianModule.rotateGuardianKey( - // 0, - // guardian2EnclavePubKey, - // RaveEvidence({ - // report: guardian2Rave.report(), - // signature: guardian2Rave.sig(), - // leafX509CertDigest: keccak256(guardian2Rave.signingCert()) - // }) - // ); - // vm.stopPrank(); - - // vm.startPrank(guardians[2]); - // vm.expectEmit(true, true, true, true); - // emit IGuardianModule.RotatedGuardianKey(guardians[2], guardian3Enclave, guardian3EnclavePubKey); - // guardianModule.rotateGuardianKey( - // 0, - // guardian3EnclavePubKey, - // RaveEvidence({ - // report: guardian3Rave.report(), - // signature: guardian3Rave.sig(), - // leafX509CertDigest: keccak256(guardian3Rave.signingCert()) - // }) - // ); + vm.startPrank(guardians[0]); + vm.expectEmit(true, true, true, true); + emit IGuardianModule.RotatedGuardianKey(guardians[0], guardian1Enclave, guardian1EnclavePubKey); + guardianModule.rotateGuardianKey( + 0, + guardian1EnclavePubKey, + TdxRegistrationData({ + teeType: TEEType.IntelTDX, + teeReportType: TeeReportType.Solidity, + cloudType: CloudType.GCP, + teeAttestationReport: abi.encodePacked(keccak256(abi.encodePacked(guardian1EnclavePubKey, blockhash(block.number)))), + workloadCollaterals: _createEmptyWorkloadCollaterals() + }) + ); vm.stopPrank(); + vm.startPrank(guardians[1]); + vm.expectEmit(true, true, true, true); + emit IGuardianModule.RotatedGuardianKey(guardians[1], guardian2Enclave, guardian2EnclavePubKey); + guardianModule.rotateGuardianKey( + 1, + guardian2EnclavePubKey, + TdxRegistrationData({ + teeType: TEEType.IntelTDX, + teeReportType: TeeReportType.Solidity, + cloudType: CloudType.GCP, + teeAttestationReport: abi.encodePacked(keccak256(abi.encodePacked(guardian2EnclavePubKey, blockhash(block.number)))), + workloadCollaterals: _createEmptyWorkloadCollaterals() + }) + ); + vm.stopPrank(); + + vm.startPrank(guardians[2]); + vm.expectEmit(true, true, true, true); + emit IGuardianModule.RotatedGuardianKey(guardians[2], guardian3Enclave, guardian3EnclavePubKey); + guardianModule.rotateGuardianKey( + 2, + guardian3EnclavePubKey, + TdxRegistrationData({ + teeType: TEEType.IntelTDX, + teeReportType: TeeReportType.Solidity, + cloudType: CloudType.GCP, + teeAttestationReport: abi.encodePacked(keccak256(abi.encodePacked(guardian3EnclavePubKey, blockhash(block.number)))), + workloadCollaterals: _createEmptyWorkloadCollaterals() + }) + ); + vm.stopPrank(); + + assertEq(guardianModule.getGuardiansEnclaveAddress(guardians[0]), guardian1Enclave, "bad enclave address1"); assertEq(guardianModule.getGuardiansEnclaveAddress(guardians[1]), guardian2Enclave, "bad enclave address2"); assertEq(guardianModule.getGuardiansEnclaveAddress(guardians[2]), guardian3Enclave, "bad enclave address3"); @@ -385,4 +427,15 @@ contract UnitTestHelper is Test, BaseScript { t.amount = amount; t.deadline = deadline; } + + function _createEmptyWorkloadCollaterals() internal pure returns (WorkloadCollaterals memory) { + return WorkloadCollaterals({ + tpmQuote: hex"", + tpmSignature: hex"", + pcrs: new MeasureablePcr[](0), + reportId: hex"", + akPub: hex"", + certs: new bytes[](0) + }); + } } diff --git a/mainnet-contracts/test/mocks/WorkloadVerifierMock.sol b/mainnet-contracts/test/mocks/WorkloadVerifierMock.sol index c445695e..4ba9607a 100644 --- a/mainnet-contracts/test/mocks/WorkloadVerifierMock.sol +++ b/mainnet-contracts/test/mocks/WorkloadVerifierMock.sol @@ -1,16 +1,28 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0 <0.9.0; -import { TEEType, TeeReportType, CloudType, WorkloadCollaterals } from "@automata-network/automata-tee-workload-measurement/interfaces/IWorkloadVerifier.sol"; +import { + TEEType, + TeeReportType, + CloudType, + WorkloadCollaterals +} from "@automata-network/automata-tee-workload-measurement/interfaces/IWorkloadVerifier.sol"; contract WorkloadVerifierMock { - function verifyAttestationAndGetMeasurementHash( - TEEType teeType, - TeeReportType teeReportType, - CloudType cloudType, + + bytes32 public mockMeasurementHash; + + function verifyAttestationAndGetMeasurementHash( + TEEType, + TeeReportType, + CloudType, bytes calldata _teeAttestationReport, - WorkloadCollaterals calldata _workloadReport + WorkloadCollaterals calldata ) external payable returns (bytes memory teeOutput, bytes32 measurementHash, bytes memory tpmExtraData) { - // TODO + return (hex"", mockMeasurementHash, _teeAttestationReport); + } + + function setMeasurementHash(bytes32 _measurementHash) external { + mockMeasurementHash = _measurementHash; } } From 3e36486be5090534e6d818e71688c8094cb717d5 Mon Sep 17 00:00:00 2001 From: Eladio Date: Mon, 2 Feb 2026 18:08:11 +0100 Subject: [PATCH 18/51] fmt --- mainnet-contracts/test/helpers/UnitTestHelper.sol | 13 +++++++++---- .../test/mocks/WorkloadVerifierMock.sol | 1 - 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/mainnet-contracts/test/helpers/UnitTestHelper.sol b/mainnet-contracts/test/helpers/UnitTestHelper.sol index 7e0b8b06..23e7a6c7 100644 --- a/mainnet-contracts/test/helpers/UnitTestHelper.sol +++ b/mainnet-contracts/test/helpers/UnitTestHelper.sol @@ -296,7 +296,9 @@ contract UnitTestHelper is Test, BaseScript { teeType: TEEType.IntelTDX, teeReportType: TeeReportType.Solidity, cloudType: CloudType.GCP, - teeAttestationReport: abi.encodePacked(keccak256(abi.encodePacked(guardian1EnclavePubKey, blockhash(block.number)))), + teeAttestationReport: abi.encodePacked( + keccak256(abi.encodePacked(guardian1EnclavePubKey, blockhash(block.number))) + ), workloadCollaterals: _createEmptyWorkloadCollaterals() }) ); @@ -312,7 +314,9 @@ contract UnitTestHelper is Test, BaseScript { teeType: TEEType.IntelTDX, teeReportType: TeeReportType.Solidity, cloudType: CloudType.GCP, - teeAttestationReport: abi.encodePacked(keccak256(abi.encodePacked(guardian2EnclavePubKey, blockhash(block.number)))), + teeAttestationReport: abi.encodePacked( + keccak256(abi.encodePacked(guardian2EnclavePubKey, blockhash(block.number))) + ), workloadCollaterals: _createEmptyWorkloadCollaterals() }) ); @@ -328,13 +332,14 @@ contract UnitTestHelper is Test, BaseScript { teeType: TEEType.IntelTDX, teeReportType: TeeReportType.Solidity, cloudType: CloudType.GCP, - teeAttestationReport: abi.encodePacked(keccak256(abi.encodePacked(guardian3EnclavePubKey, blockhash(block.number)))), + teeAttestationReport: abi.encodePacked( + keccak256(abi.encodePacked(guardian3EnclavePubKey, blockhash(block.number))) + ), workloadCollaterals: _createEmptyWorkloadCollaterals() }) ); vm.stopPrank(); - assertEq(guardianModule.getGuardiansEnclaveAddress(guardians[0]), guardian1Enclave, "bad enclave address1"); assertEq(guardianModule.getGuardiansEnclaveAddress(guardians[1]), guardian2Enclave, "bad enclave address2"); assertEq(guardianModule.getGuardiansEnclaveAddress(guardians[2]), guardian3Enclave, "bad enclave address3"); diff --git a/mainnet-contracts/test/mocks/WorkloadVerifierMock.sol b/mainnet-contracts/test/mocks/WorkloadVerifierMock.sol index 4ba9607a..00fc6c3d 100644 --- a/mainnet-contracts/test/mocks/WorkloadVerifierMock.sol +++ b/mainnet-contracts/test/mocks/WorkloadVerifierMock.sol @@ -9,7 +9,6 @@ import { } from "@automata-network/automata-tee-workload-measurement/interfaces/IWorkloadVerifier.sol"; contract WorkloadVerifierMock { - bytes32 public mockMeasurementHash; function verifyAttestationAndGetMeasurementHash( From dd987a8b8e86adb89a2f188aecd8ac9fa61463c0 Mon Sep 17 00:00:00 2001 From: Eladio Date: Mon, 2 Feb 2026 18:35:17 +0100 Subject: [PATCH 19/51] Added tests and added missing checks to GuardianModule --- mainnet-contracts/src/GuardianModule.sol | 12 ++- .../test/unit/GuardianModule.t.sol | 98 ++++++++++++++----- 2 files changed, 81 insertions(+), 29 deletions(-) diff --git a/mainnet-contracts/src/GuardianModule.sol b/mainnet-contracts/src/GuardianModule.sol index 03812c4c..cc9f5d5f 100644 --- a/mainnet-contracts/src/GuardianModule.sol +++ b/mainnet-contracts/src/GuardianModule.sol @@ -295,6 +295,16 @@ contract GuardianModule is AccessManaged, IGuardianModule { bytes calldata pubKey, TdxRegistrationData calldata data // TDX DCAP ) external payable { + address guardian = msg.sender; + + if (!_guardians.contains(guardian)) { + revert Unauthorized(); + } + + if (pubKey.length != _ECDSA_KEY_LENGTH) { + revert InvalidECDSAPubKey(); + } + (, bytes32 measurementHash, bytes memory tpmExtraData) = WORKLOAD_VERIFIER .verifyAttestationAndGetMeasurementHash{ value: msg.value }( data.teeType, data.teeReportType, data.cloudType, data.teeAttestationReport, data.workloadCollaterals @@ -306,8 +316,6 @@ contract GuardianModule is AccessManaged, IGuardianModule { require(bytes32(tpmExtraData) == expectedCommitment, CommitmentMismatch()); // Register guardian - - address guardian = msg.sender; // pubKey[1:] means we need to strip the first byte '0x' if we want to get the correct address address computedAddress = address(uint160(uint256(keccak256(pubKey[1:])))); diff --git a/mainnet-contracts/test/unit/GuardianModule.t.sol b/mainnet-contracts/test/unit/GuardianModule.t.sol index 5affee21..3c7bcda9 100644 --- a/mainnet-contracts/test/unit/GuardianModule.t.sol +++ b/mainnet-contracts/test/unit/GuardianModule.t.sol @@ -4,6 +4,9 @@ pragma solidity >=0.8.0 <0.9.0; import { UnitTestHelper } from "../helpers/UnitTestHelper.sol"; import { IGuardianModule } from "../../src/interface/IGuardianModule.sol"; import { Unauthorized } from "../../src/Errors.sol"; +import { TEEType, TeeReportType, CloudType } from "@automata-network/automata-tee-workload-measurement/lib/LibTEE.sol"; +import { TdxRegistrationData } from "../../src/struct/GuardianModuleStructs.sol"; +import { WorkloadVerifierMock } from "../mocks/WorkloadVerifierMock.sol"; contract GuardianModuleTest is UnitTestHelper { function setUp() public override { @@ -34,21 +37,77 @@ contract GuardianModuleTest is UnitTestHelper { guardianModule.setThreshold(50); } - // TODO [TDX] Update rotateGuardianKey tests - // function test_rotateGuardianKey_from_non_guardian_reverts() public { - // RaveEvidence memory evidence; - // vm.expectRevert(Unauthorized.selector); - // guardianModule.rotateGuardianKey(0, new bytes(55), evidence); - // } + function test_rotateGuardianKey_from_non_guardian_reverts() public { + vm.expectRevert(Unauthorized.selector); + guardianModule.rotateGuardianKey( + 0, + new bytes(55), + TdxRegistrationData({ + teeType: TEEType.IntelTDX, + teeReportType: TeeReportType.Solidity, + cloudType: CloudType.GCP, + teeAttestationReport: hex"", + workloadCollaterals: _createEmptyWorkloadCollaterals() + }) + ); + } - // function test_rotateGuardianKey_to_invalid_pubKey_everts() public { - // RaveEvidence memory evidence; + function test_rotateGuardianKey_to_invalid_pubKey_reverts() public { + vm.startPrank(guardian1); + + vm.expectRevert(IGuardianModule.InvalidECDSAPubKey.selector); + guardianModule.rotateGuardianKey( + 0, + new bytes(55), + TdxRegistrationData({ + teeType: TEEType.IntelTDX, + teeReportType: TeeReportType.Solidity, + cloudType: CloudType.GCP, + teeAttestationReport: hex"", + workloadCollaterals: _createEmptyWorkloadCollaterals() + }) + ); + } - // vm.startPrank(guardian1); + function test_rotateGuardianKey_with_invalid_measurement_reverts() public { + vm.startPrank(guardian1); + + WorkloadVerifierMock(address(verifier)).setMeasurementHash(bytes32("some invalid measurement hash")); + + vm.expectRevert(IGuardianModule.InvalidMeasurement.selector); + guardianModule.rotateGuardianKey( + 0, + guardian3EnclavePubKey, + TdxRegistrationData({ + teeType: TEEType.IntelTDX, + teeReportType: TeeReportType.Solidity, + cloudType: CloudType.GCP, + teeAttestationReport: hex"", + workloadCollaterals: _createEmptyWorkloadCollaterals() + }) + ); + vm.stopPrank(); + } - // vm.expectRevert(IGuardianModule.InvalidECDSAPubKey.selector); - // guardianModule.rotateGuardianKey(0, new bytes(55), evidence); - // } + function test_rotateGuardianKey_with_invalid_commitment_mismatch() public { + vm.startPrank(guardian1); + + vm.expectRevert(IGuardianModule.CommitmentMismatch.selector); + guardianModule.rotateGuardianKey( + 0, + guardian3EnclavePubKey, + TdxRegistrationData({ + teeType: TEEType.IntelTDX, + teeReportType: TeeReportType.Solidity, + cloudType: CloudType.GCP, + teeAttestationReport: abi.encodePacked( + keccak256(abi.encodePacked(guardian2EnclavePubKey, blockhash(block.number))) + ), + workloadCollaterals: _createEmptyWorkloadCollaterals() + }) + ); + vm.stopPrank(); + } function test_addGuardian(address guardian) public assumeEOA(guardian) { vm.startPrank(DAO); @@ -106,21 +165,6 @@ contract GuardianModuleTest is UnitTestHelper { vm.expectRevert(); guardianModule.setThreshold(5); } - // TODO [TDX] Update rotateGuardianKey tests - // function test_rotateGuardianKey_with_invalid_rave_reverts() public { - // Guardian2RaveEvidence guardian2Rave = new Guardian2RaveEvidence(); - - // vm.startPrank(guardian1); - - // RaveEvidence memory rave = RaveEvidence({ - // report: guardian2Rave.report(), - // signature: guardian2Rave.sig(), - // leafX509CertDigest: keccak256(guardian2Rave.signingCert()) - // }); - - // vm.expectRevert(IGuardianModule.InvalidRAVE.selector); - // guardianModule.rotateGuardianKey(0, guardian3EnclavePubKey, rave); - // } // Invalid signature reverts with unauthorized function test_validateSkipProvisioning_reverts() public { From 3523a0d67c76ce273f084f9cdac29c644576f442 Mon Sep 17 00:00:00 2001 From: Eladio Date: Mon, 9 Feb 2026 17:58:14 +0100 Subject: [PATCH 20/51] Applied changes to GuardianModule (WIP) --- mainnet-contracts/foundry.lock | 3 + .../lib/automata-tee-workload-measurement | 2 +- mainnet-contracts/src/GuardianModule.sol | 275 +++++++++++------- .../src/interface/IGuardianModule.sol | 89 +++--- .../src/struct/GuardianModuleStructs.sol | 36 --- 5 files changed, 222 insertions(+), 183 deletions(-) delete mode 100644 mainnet-contracts/src/struct/GuardianModuleStructs.sol diff --git a/mainnet-contracts/foundry.lock b/mainnet-contracts/foundry.lock index cae4ef6e..b5ef6bc6 100644 --- a/mainnet-contracts/foundry.lock +++ b/mainnet-contracts/foundry.lock @@ -8,6 +8,9 @@ "rev": "9c96312657f2a905003f6ebf565d5742422f24a2" } }, + "lib/automata-tee-workload-measurement": { + "rev": "c3bcd68f4b887f86374cc47b31041bf2d667e7d3" + }, "lib/automata-tpm-attestation": { "rev": "1a3ab2bc4886ac5313365f94e3d60dcf01fd9c41" }, diff --git a/mainnet-contracts/lib/automata-tee-workload-measurement b/mainnet-contracts/lib/automata-tee-workload-measurement index c3bcd68f..0ae64e7e 160000 --- a/mainnet-contracts/lib/automata-tee-workload-measurement +++ b/mainnet-contracts/lib/automata-tee-workload-measurement @@ -1 +1 @@ -Subproject commit c3bcd68f4b887f86374cc47b31041bf2d667e7d3 +Subproject commit 0ae64e7ee8279ad1ed4cce8f31c5cf08202700a9 diff --git a/mainnet-contracts/src/GuardianModule.sol b/mainnet-contracts/src/GuardianModule.sol index cc9f5d5f..d4c56ac7 100644 --- a/mainnet-contracts/src/GuardianModule.sol +++ b/mainnet-contracts/src/GuardianModule.sol @@ -10,8 +10,7 @@ import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableS import { LibGuardianMessages } from "./LibGuardianMessages.sol"; import { Address } from "@openzeppelin/contracts/utils/Address.sol"; import { StoppedValidatorInfo } from "./struct/StoppedValidatorInfo.sol"; -import { IWorkloadVerifier } from "@automata-network/automata-tee-workload-measurement/interfaces/IWorkloadVerifier.sol"; -import { TdxRegistrationData, GoldenMeasurementInfo, GuardianData } from "./struct/GuardianModuleStructs.sol"; +import { ISessionRegistry, PublicIdentity, CVMSession } from "@automata-network/automata-tee-workload-measurement/interfaces/registries/ISessionRegistry.sol"; /** * @title Guardian module @@ -37,9 +36,9 @@ contract GuardianModule is AccessManaged, IGuardianModule { uint256 internal constant _EJECTION_THRESHOLD_BALANCE = 31.75 ether; /** - * @notice Workload Verifier smart contract + * @notice Session Registry smart contract */ - IWorkloadVerifier public immutable WORKLOAD_VERIFIER; + ISessionRegistry public immutable SESSION_REGISTRY; /** * @dev Guardians set @@ -57,26 +56,39 @@ contract GuardianModule is AccessManaged, IGuardianModule { uint256 internal _ejectionThreshold; /** - * @dev Mapping of a Guardian's EOA to enclave data + * @dev Enclave data + * The guardian doesn't know the Secret Key of an enclave wallet */ - mapping(address guardian => GuardianData data) internal _guardianEnclaves; + struct GuardianData { + uint256 nonce; + bytes enclavePubKey; + address enclaveAddress; + } /** - * @dev Mapping of Golden Measurement registry hash to GoldenMeasurementInfo + * @dev Mapping of a Guardian's fingerprint to enclave data */ - mapping(bytes32 hash => GoldenMeasurementInfo info) internal _goldenMeasurements; + mapping(bytes32 ownerFingerprint => GuardianData data) + internal _guardianEnclaves; - constructor(IWorkloadVerifier verifier, address[] memory guardians, uint256 threshold, address pufferAuthority) - payable - AccessManaged(pufferAuthority) - { - if (address(verifier) == address(0)) { + /** + * @dev Mapping of allowed workload IDs (can be added/removed) + */ + mapping(bytes32 workloadId => bool allowed) internal _allowedWorkloads; + + constructor( + ISessionRegistry sessionRegistry, + address[] memory guardians, + uint256 threshold, + address pufferAuthority + ) payable AccessManaged(pufferAuthority) { + if (address(sessionRegistry) == address(0)) { revert InvalidAddress(); } if (address(pufferAuthority) == address(0)) { revert InvalidAddress(); } - WORKLOAD_VERIFIER = verifier; + SESSION_REGISTRY = sessionRegistry; for (uint256 i = 0; i < guardians.length; ++i) { _addGuardian(guardians[i]); } @@ -84,7 +96,7 @@ contract GuardianModule is AccessManaged, IGuardianModule { _setThreshold(threshold); } - receive() external payable { } + receive() external payable {} /* * @notice Splits the funds among the guardians @@ -108,15 +120,19 @@ contract GuardianModule is AccessManaged, IGuardianModule { /** * @inheritdoc IGuardianModule */ - function validateSkipProvisioning(bytes32 moduleName, uint256 skippedIndex, bytes[] calldata eoaSignatures) - external - view - { - bytes32 signedMessageHash = LibGuardianMessages._getSkipProvisioningMessage(moduleName, skippedIndex); + function validateSkipProvisioning( + bytes32 moduleName, + uint256 skippedIndex, + bytes[] calldata eoaSignatures + ) external view { + bytes32 signedMessageHash = LibGuardianMessages + ._getSkipProvisioningMessage(moduleName, skippedIndex); // Check the signatures - bool validSignatures = - validateGuardiansEOASignatures({ eoaSignatures: eoaSignatures, signedMessageHash: signedMessageHash }); + bool validSignatures = validateGuardiansEOASignatures({ + eoaSignatures: eoaSignatures, + signedMessageHash: signedMessageHash + }); if (!validSignatures) { revert Unauthorized(); @@ -135,13 +151,14 @@ contract GuardianModule is AccessManaged, IGuardianModule { bytes[] calldata enclaveSignatures ) external view { // Recreate the message hash - bytes32 signedMessageHash = LibGuardianMessages._getBeaconDepositMessageToBeSigned({ - pufferModuleIndex: pufferModuleIndex, - pubKey: pubKey, - signature: signature, - withdrawalCredentials: withdrawalCredentials, - depositDataRoot: depositDataRoot - }); + bytes32 signedMessageHash = LibGuardianMessages + ._getBeaconDepositMessageToBeSigned({ + pufferModuleIndex: pufferModuleIndex, + pubKey: pubKey, + signature: signature, + withdrawalCredentials: withdrawalCredentials, + depositDataRoot: depositDataRoot + }); // Check the signatures bool validSignatures = validateGuardiansEnclaveSignatures({ @@ -157,15 +174,18 @@ contract GuardianModule is AccessManaged, IGuardianModule { /** * @inheritdoc IGuardianModule */ - function validateBatchWithdrawals(StoppedValidatorInfo[] calldata validatorInfos, bytes[] calldata eoaSignatures) - external - view - { - bytes32 signedMessageHash = LibGuardianMessages._getHandleBatchWithdrawalMessage(validatorInfos); + function validateBatchWithdrawals( + StoppedValidatorInfo[] calldata validatorInfos, + bytes[] calldata eoaSignatures + ) external view { + bytes32 signedMessageHash = LibGuardianMessages + ._getHandleBatchWithdrawalMessage(validatorInfos); // Check the signatures - bool validSignatures = - validateGuardiansEOASignatures({ eoaSignatures: eoaSignatures, signedMessageHash: signedMessageHash }); + bool validSignatures = validateGuardiansEOASignatures({ + eoaSignatures: eoaSignatures, + signedMessageHash: signedMessageHash + }); if (!validSignatures) { revert Unauthorized(); @@ -181,12 +201,17 @@ contract GuardianModule is AccessManaged, IGuardianModule { bytes[] calldata eoaSignatures ) external view { // Recreate the message hash - bytes32 signedMessageHash = - LibGuardianMessages._getSetNumberOfValidatorsMessage(newNumberOfValidators, epochNumber); + bytes32 signedMessageHash = LibGuardianMessages + ._getSetNumberOfValidatorsMessage( + newNumberOfValidators, + epochNumber + ); // Check the signatures - bool validSignatures = - validateGuardiansEOASignatures({ eoaSignatures: eoaSignatures, signedMessageHash: signedMessageHash }); + bool validSignatures = validateGuardiansEOASignatures({ + eoaSignatures: eoaSignatures, + signedMessageHash: signedMessageHash + }); if (!validSignatures) { revert Unauthorized(); @@ -196,23 +221,31 @@ contract GuardianModule is AccessManaged, IGuardianModule { /** * @inheritdoc IGuardianModule */ - function validateGuardiansEOASignatures(bytes[] calldata eoaSignatures, bytes32 signedMessageHash) - public - view - returns (bool) - { - return _validateSignatures(_guardians.values(), eoaSignatures, signedMessageHash); + function validateGuardiansEOASignatures( + bytes[] calldata eoaSignatures, + bytes32 signedMessageHash + ) public view returns (bool) { + return + _validateSignatures( + _guardians.values(), + eoaSignatures, + signedMessageHash + ); } /** * @inheritdoc IGuardianModule */ - function validateGuardiansEnclaveSignatures(bytes[] calldata enclaveSignatures, bytes32 signedMessageHash) - public - view - returns (bool) - { - return _validateSignatures(getGuardiansEnclaveAddresses(), enclaveSignatures, signedMessageHash); + function validateGuardiansEnclaveSignatures( + bytes[] calldata enclaveSignatures, + bytes32 signedMessageHash + ) public view returns (bool) { + return + _validateSignatures( + getGuardiansEnclaveAddresses(), + enclaveSignatures, + signedMessageHash + ); } /** @@ -227,19 +260,9 @@ contract GuardianModule is AccessManaged, IGuardianModule { * @inheritdoc IGuardianModule * @dev Restricted to the DAO */ - function registerGoldenMeasurement(bytes32 hash, GoldenMeasurementInfo calldata info) external restricted { - require(hash != bytes32(0), InvalidData()); - _goldenMeasurements[hash] = info; - emit GoldenMeasurementRegistered(hash, info); - } - - /** - * @inheritdoc IGuardianModule - * @dev Restricted to the DAO - */ - function deregisterGoldenMeasurement(bytes32 hash) external restricted { - delete _goldenMeasurements[hash]; - emit GoldenMeasurementDeregistered(hash); + function setAllowedWorkload(bytes32 workloadId, bool allowed) external restricted { + _allowedWorkloads[workloadId] = allowed; + emit WorkloadAllowanceChanged(workloadId, allowed); } /** @@ -258,7 +281,7 @@ contract GuardianModule is AccessManaged, IGuardianModule { function removeGuardian(address guardian) external restricted { splitGuardianFunds(); - (bool success) = _guardians.remove(guardian); + bool success = _guardians.remove(guardian); if (success) { emit GuardianRemoved(guardian); } @@ -290,39 +313,61 @@ contract GuardianModule is AccessManaged, IGuardianModule { return _guardians.values(); } + /** + * @inheritdoc IGuardianModule + */ function rotateGuardianKey( - uint256 blockNumber, + bytes32 sessionId, + PublicIdentity calldata sessionKey, + uint256 nonce, bytes calldata pubKey, - TdxRegistrationData calldata data // TDX DCAP - ) external payable { - address guardian = msg.sender; - - if (!_guardians.contains(guardian)) { - revert Unauthorized(); - } - - if (pubKey.length != _ECDSA_KEY_LENGTH) { - revert InvalidECDSAPubKey(); - } - - (, bytes32 measurementHash, bytes memory tpmExtraData) = WORKLOAD_VERIFIER - .verifyAttestationAndGetMeasurementHash{ value: msg.value }( - data.teeType, data.teeReportType, data.cloudType, data.teeAttestationReport, data.workloadCollaterals + bytes calldata signature + ) external { + // Build rotation message (replay protection) + bytes32 rotationMessage = keccak256( + abi.encode( + "ROTATE_GUARDIAN_KEY", + nonce, + pubKey, + block.chainid, + address(this) + ) + ); + bool valid = SESSION_REGISTRY.verifySessionSignature( + sessionId, + sessionKey, + rotationMessage, + signature + ); + require(valid, InvalidSignature()); + // Signature verified: session is active and signature is valid + + bytes32 ownerFingerprint = SESSION_REGISTRY.getSessionOwner(sessionId); + + // Optional: Get more context via SESSION_REGISTRY.getSession(sessionId) + // Returns CVMSession with: + // - workloadId: registered workload identifier + // - baseImageId: trusted base image identifier + // - platformProfileId: TEE platform (e.g., "gcp-tdx", "azure-snp") + // - variantId: machineType variant + // Compare session.workloadId with allowedWorkloads mapping + CVMSession memory session = SESSION_REGISTRY.getSession(sessionId); + require(_allowedWorkloads[session.workloadId], WorkloadNotAllowed()); + + // Verify nonce for replay protection (starts at 0 for new guardians) + GuardianData storage stored = _guardianEnclaves[ownerFingerprint]; + require(stored.nonce == nonce, InvalidNonce()); + + address computedAddress = address( + uint160(uint256(keccak256(pubKey[1:]))) ); - require(_goldenMeasurements[measurementHash].valid, InvalidMeasurement()); - - bytes32 expectedCommitment = keccak256(abi.encodePacked(pubKey, blockhash(blockNumber))); - require(bytes32(tpmExtraData) == expectedCommitment, CommitmentMismatch()); - - // Register guardian - // pubKey[1:] means we need to strip the first byte '0x' if we want to get the correct address - address computedAddress = address(uint160(uint256(keccak256(pubKey[1:])))); - - _guardianEnclaves[guardian].enclaveAddress = computedAddress; - _guardianEnclaves[guardian].enclavePubKey = pubKey; + // Update guardian's enclave data + stored.enclavePubKey = pubKey; + stored.nonce += 1; + stored.enclaveAddress = computedAddress; - emit RotatedGuardianKey(guardian, computedAddress, pubKey); + emit RotatedGuardianKey(ownerFingerprint, computedAddress); } /** @@ -335,21 +380,28 @@ contract GuardianModule is AccessManaged, IGuardianModule { /** * @inheritdoc IGuardianModule */ - function getGuardiansEnclaveAddress(address guardian) external view returns (address) { + function getGuardiansEnclaveAddress( + address guardian + ) external view returns (address) { return _guardianEnclaves[guardian].enclaveAddress; } /** * @inheritdoc IGuardianModule */ - function getGuardiansEnclaveAddresses() public view returns (address[] memory) { + function getGuardiansEnclaveAddresses() + public + view + returns (address[] memory) + { uint256 guardiansLength = _guardians.length(); address[] memory enclaveAddresses = new address[](guardiansLength); for (uint256 i; i < guardiansLength; ++i) { // If the guardian doesn't have an enclave address, we use `0xdead` address // The reason for this is that we use .tryRecover in signature verification, and a valid signature can be crafted to recover to address(0) - address enclaveAddress = _guardianEnclaves[_guardians.at(i)].enclaveAddress == address(0) + address enclaveAddress = _guardianEnclaves[_guardians.at(i)] + .enclaveAddress == address(0) ? address(0x000000000000000000000000000000000000dEaD) : _guardianEnclaves[_guardians.at(i)].enclaveAddress; enclaveAddresses[i] = enclaveAddress; @@ -361,12 +413,17 @@ contract GuardianModule is AccessManaged, IGuardianModule { /** * @inheritdoc IGuardianModule */ - function getGuardiansEnclavePubkeys() external view returns (bytes[] memory) { + function getGuardiansEnclavePubkeys() + external + view + returns (bytes[] memory) + { uint256 guardiansLength = _guardians.length(); bytes[] memory enclavePubkeys = new bytes[](guardiansLength); for (uint256 i; i < guardiansLength; ++i) { - enclavePubkeys[i] = _guardianEnclaves[_guardians.at(i)].enclavePubKey; + enclavePubkeys[i] = _guardianEnclaves[_guardians.at(i)] + .enclavePubKey; } return enclavePubkeys; @@ -382,8 +439,10 @@ contract GuardianModule is AccessManaged, IGuardianModule { /** * @inheritdoc IGuardianModule */ - function getGoldenMeasurement(bytes32 hash) external view returns (GoldenMeasurementInfo memory) { - return _goldenMeasurements[hash]; + function isWorkloadAllowed( + bytes32 workloadId + ) external view returns (bool) { + return _allowedWorkloads[workloadId]; } function _addGuardian(address newGuardian) internal { @@ -425,17 +484,17 @@ contract GuardianModule is AccessManaged, IGuardianModule { * @param signedMessageHash The hash of the signed message * @return A boolean indicating whether the signatures are valid */ - function _validateSignatures(address[] memory signers, bytes[] calldata signatures, bytes32 signedMessageHash) - internal - view - returns (bool) - { + function _validateSignatures( + address[] memory signers, + bytes[] calldata signatures, + bytes32 signedMessageHash + ) internal view returns (bool) { uint256 validSignatures; // We only count signature as valid if it's from the correct signer for (uint256 i; i < signers.length; ++i) { - (address currentSigner, ECDSA.RecoverError recoverError,) = - ECDSA.tryRecover(signedMessageHash, signatures[i]); + (address currentSigner, ECDSA.RecoverError recoverError, ) = ECDSA + .tryRecover(signedMessageHash, signatures[i]); if (recoverError == ECDSA.RecoverError.NoError) { if (currentSigner == signers[i]) { ++validSignatures; diff --git a/mainnet-contracts/src/interface/IGuardianModule.sol b/mainnet-contracts/src/interface/IGuardianModule.sol index 73573d1a..84219333 100644 --- a/mainnet-contracts/src/interface/IGuardianModule.sol +++ b/mainnet-contracts/src/interface/IGuardianModule.sol @@ -2,7 +2,7 @@ pragma solidity >=0.8.0 <0.9.0; import { StoppedValidatorInfo } from "../struct/StoppedValidatorInfo.sol"; -import { TdxRegistrationData, GoldenMeasurementInfo } from "../struct/GuardianModuleStructs.sol"; +import { PublicIdentity } from "@automata-network/automata-tee-workload-measurement/types/Common.sol"; /** * @title IGuardianModule interface @@ -39,6 +39,24 @@ interface IGuardianModule { */ error CommitmentMismatch(); + /** + * @notice Thrown if the signature is not valid + * @dev Signature "0x8baa579f" + */ + error InvalidSignature(); + + /** + * @notice Thrown if the workload is not allowed + * @dev Signature "0x37c9b5f1" + */ + error WorkloadNotAllowed(); + + /** + * @notice Thrown if the nonce is not valid + * @dev Signature "0x756688fe" + */ + error InvalidNonce(); + /** * @notice Emitted when the ejection threshold is changed * @param oldThreshold is the old threshold value @@ -71,27 +89,20 @@ interface IGuardianModule { /** * @notice Emitted when the guardian changes guardian enclave address - * @param guardian is the address outside of the enclave - * @param guardianEnclave is the enclave address - * @param pubKey is the public key - * @dev Signature "0x14720919b20fceff2a396c4973d37c6087e4619d40c8f4003d8e44ee127461a2" + * @param ownerFingerprint The fingerprint of the guardian's public key + * @param computedAddress The computed address from the new public key + * @dev Signature "0x6e41f97e85009a93fbd7a9e9c885b782819739d41a903d21bb4ad7a40d1af83a" */ - event RotatedGuardianKey(address guardian, address guardianEnclave, bytes pubKey); + event RotatedGuardianKey(bytes32 ownerFingerprint, address computedAddress); /** - * @notice Emitted when a new GoldenMeasurement is registered - * @dev 0xe5cf28b6abd2dfc43e26d77ce57814cc723f1ee29925cd92112ea764eb1e6775 - * @param hash id of the GoldenMeasurement - * @param info data of the GoldenMeasurement + * @notice Emitted when a workload allowance is changed + * @param workloadId id of the workload + * @param allowed bool indicating whether the workload is allowed or not + * @dev Signature "0x73013b875c0fba87c394f60e5697094d91b6bdce94ca3c53133a34bd980e114d" */ - event GoldenMeasurementRegistered(bytes32 hash, GoldenMeasurementInfo info); + event WorkloadAllowanceChanged(bytes32 workloadId, bool allowed); - /** - * @notice Emitted when a GoldenMeasurement is deregistered - * @dev 0x3b86a29684cb98125d16491ad1dd1d2c52f8446ba9ba6ef696cef58743d8fa84 - * @param hash id of the GoldenMeasurement - */ - event GoldenMeasurementDeregistered(bytes32 hash); /** * @notice Returns the enclave address registered to `guardian` @@ -108,17 +119,12 @@ interface IGuardianModule { function getEjectionThreshold() external view returns (uint256); /** - * @notice Registers Golden Measurement - * @param hash id of the Golden Measurement - * @param info Info of the Golden Measurement - */ - function registerGoldenMeasurement(bytes32 hash, GoldenMeasurementInfo calldata info) external; - - /** - * @notice Deregisters Golden Measurement - * @param hash id of the Golden Measurement + * @notice Set allowed workloads for guardians + * @dev Workload policies are managed in WorkloadRegistry + * @param workloadId Id of the workload + * @param allowed Bool indicating whether the workload is allowed or not */ - function deregisterGoldenMeasurement(bytes32 hash) external; + function setAllowedWorkload(bytes32 workloadId, bool allowed) external; /** * @notice Validates the update of the number of validators @@ -237,14 +243,21 @@ interface IGuardianModule { /** * @notice Rotates guardian's key - * @dev If he caller is not a valid guardian or if the TdxRegistrationData is not valid the tx will revert - * @param blockNumber is the block number + * @dev Guardian = session owner (NOT msg.sender) + * Uses nonce for replay protection (starts at 0 for new guardians) + * @param sessionId is the session id of the guardian + * @param sessionKey is the session key of the guardian + * @param nonce is the nonce for replay protection * @param pubKey is the public key of the new signature - * @param data TdxRegistrationData to verify - */ - function rotateGuardianKey(uint256 blockNumber, bytes calldata pubKey, TdxRegistrationData calldata data) - external - payable; + * @param signature is the signature to verify + */ + function rotateGuardianKey( + bytes32 sessionId, + PublicIdentity calldata sessionKey, + uint256 nonce, + bytes calldata pubKey, + bytes calldata signature + ) external; /** * @notice Returns the guardians enclave addresses @@ -264,9 +277,9 @@ interface IGuardianModule { function isGuardian(address account) external view returns (bool); /** - * @notice Returns the info of a GoldenMeasurement - * @param hash id of the GoldenMeasurement - * @return Info of the GoldenMeasurement + * @notice Returns the workload allowed status + * @param workloadId The workload id to check + * @return A boolean indicating whether the workload is allowed */ - function getGoldenMeasurement(bytes32 hash) external view returns (GoldenMeasurementInfo memory); + function isWorkloadAllowed(bytes32 workloadId) external view returns (bool); } diff --git a/mainnet-contracts/src/struct/GuardianModuleStructs.sol b/mainnet-contracts/src/struct/GuardianModuleStructs.sol deleted file mode 100644 index 4d99ccf8..00000000 --- a/mainnet-contracts/src/struct/GuardianModuleStructs.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity >=0.8.0 <0.9.0; - -import { TEEType, TeeReportType, CloudType } from "@automata-network/automata-tee-workload-measurement/lib/LibTEE.sol"; -import { WorkloadCollaterals } from - "@automata-network/automata-tee-workload-measurement/interfaces/IWorkloadVerifier.sol"; - -/** - * @dev Tdx Registration Data - */ -struct TdxRegistrationData { - TEEType teeType; - TeeReportType teeReportType; - CloudType cloudType; - bytes teeAttestationReport; - WorkloadCollaterals workloadCollaterals; -} - -/** - * @dev Golden Measurement Info - */ -struct GoldenMeasurementInfo { - bool valid; - TEEType teeType; - CloudType cloudType; - string tag; // e.g., "guardian-v1.0.0" -} - -/** - * @dev Enclave data - * The guardian doesn't know the Secret Key of an enclave wallet - */ -struct GuardianData { - bytes enclavePubKey; - address enclaveAddress; -} From 50297ba3c43904fac51e937c4a78b690b3d79177 Mon Sep 17 00:00:00 2001 From: Eladio Date: Fri, 13 Feb 2026 12:27:56 +0100 Subject: [PATCH 21/51] Adapted code, scripts, and partially tests (WIP) --- .../script/DeployEverything.s.sol | 10 +- .../script/DeployGuardians.s.sol | 10 +- mainnet-contracts/script/DeployPuffer.s.sol | 4 +- .../script/DeploymentStructs.sol | 4 +- ...GenerateBLSKeysAndRegisterValidators.s.sol | 4 +- mainnet-contracts/script/SetupAccess.s.sol | 13 +- mainnet-contracts/src/GuardianModule.sol | 227 +++++++----------- mainnet-contracts/src/PufferProtocol.sol | 15 +- .../src/interface/IGuardianModule.sol | 63 ++--- .../src/interface/IPufferProtocol.sol | 4 +- .../test/helpers/IntegrationTestHelper.sol | 12 +- .../test/helpers/UnitTestHelper.sol | 138 ++--------- .../test/mocks/SessionRegistryMock.sol | 24 ++ .../test/mocks/WorkloadVerifierMock.sol | 27 --- .../test/unit/GuardianModule.t.sol | 78 +----- .../test/unit/PufferProtocol.t.sol | 11 - 16 files changed, 186 insertions(+), 458 deletions(-) create mode 100644 mainnet-contracts/test/mocks/SessionRegistryMock.sol delete mode 100644 mainnet-contracts/test/mocks/WorkloadVerifierMock.sol diff --git a/mainnet-contracts/script/DeployEverything.s.sol b/mainnet-contracts/script/DeployEverything.s.sol index b7845ffd..ea847a18 100644 --- a/mainnet-contracts/script/DeployEverything.s.sol +++ b/mainnet-contracts/script/DeployEverything.s.sol @@ -16,19 +16,19 @@ import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy import { GenerateRevenueDepositorCalldata } from "script/AccessManagerMigrations/06_GenerateRevenueDepositorCalldata.s.sol"; import { MockAeraVault } from "test/mocks/MockAeraVault.sol"; -import { IWorkloadVerifier } from "@automata-network/automata-tee-workload-measurement/interfaces/IWorkloadVerifier.sol"; +import { ISessionRegistry } from "@automata-network/automata-tee-workload-measurement/interfaces/registries/ISessionRegistry.sol"; /** * @title Deploy all protocol contracts * @author Puffer Finance * @notice Deploys pufETH (upgrade it in test environment), Guardians, Oracle, Puffer, and sets up the access control * @dev Example on how to run the script - * forge script script/DeployEverything.s.sol:DeployEverything --rpc-url=$RPC_URL --sig 'run(address, address[] calldata, uint256, address)' "[$DEV_WALLET]" 1 $DEV_WALLET --broadcast + * forge script script/DeployEverything.s.sol:DeployEverything --rpc-url=$RPC_URL --sig 'run(address, address[] calldata, uint256, address)' "[$DEV_WALLET]" 1 $DEV_WALLET --broadcast */ contract DeployEverything is BaseScript { address DAO; - function run(address workloadVerifier, address[] calldata guardians, uint256 threshold, address paymaster) + function run(address sessionRegistry, address[] calldata guardians, uint256 threshold, address paymaster) public returns (PufferProtocolDeployment memory, BridgingDeployment memory) { @@ -46,7 +46,7 @@ contract DeployEverything is BaseScript { deployment.accessManager = puffETHDeployment.accessManager; GuardiansDeployment memory guardiansDeployment = new DeployGuardians().run( - IWorkloadVerifier(workloadVerifier), AccessManager(puffETHDeployment.accessManager), guardians, threshold + ISessionRegistry(sessionRegistry), AccessManager(puffETHDeployment.accessManager), guardians, threshold ); address pufferOracle = new DeployPufferOracle().run( @@ -94,7 +94,7 @@ contract DeployEverything is BaseScript { vm.serializeAddress(obj, "guardianModule", deployment.guardianModule); vm.serializeAddress(obj, "accessManager", deployment.accessManager); - vm.serializeAddress(obj, "workloadVerifier", deployment.workloadVerifier); + vm.serializeAddress(obj, "sessionRegistry", deployment.sessionRegistry); vm.serializeAddress(obj, "moduleBeacon", deployment.beacon); vm.serializeAddress(obj, "moduleManager", deployment.moduleManager); vm.serializeAddress(obj, "validatorTicket", deployment.validatorTicket); diff --git a/mainnet-contracts/script/DeployGuardians.s.sol b/mainnet-contracts/script/DeployGuardians.s.sol index 211b8c14..b1a5cf9a 100644 --- a/mainnet-contracts/script/DeployGuardians.s.sol +++ b/mainnet-contracts/script/DeployGuardians.s.sol @@ -5,24 +5,24 @@ import { BaseScript } from "script/BaseScript.s.sol"; import { GuardianModule } from "../src/GuardianModule.sol"; import { AccessManager } from "@openzeppelin/contracts/access/manager/AccessManager.sol"; import { GuardiansDeployment } from "./DeploymentStructs.sol"; -import { IWorkloadVerifier } from "@automata-network/automata-tee-workload-measurement/interfaces/IWorkloadVerifier.sol"; +import { ISessionRegistry } from "@automata-network/automata-tee-workload-measurement/interfaces/registries/ISessionRegistry.sol"; -// forge script script/1_DeployGuardians.s.sol:DeployGuardians --rpc-url=$EPHEMERY_RPC_URL --sig 'run(address, address, address[] calldata, uint256)' "[0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0]" 1 +// forge script script/1_DeployGuardians.s.sol:DeployGuardians --rpc-url=$EPHEMERY_RPC_URL --sig 'run(address, address, address[] calldata, uint256)' "[0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0]" 1 contract DeployGuardians is BaseScript { function run( - IWorkloadVerifier workloadVerifier, + ISessionRegistry sessionRegistry, AccessManager accessManager, address[] calldata guardians, uint256 threshold ) public broadcast returns (GuardiansDeployment memory) { vm.label(address(accessManager), "AccessManager"); - GuardianModule module = new GuardianModule(workloadVerifier, guardians, threshold, address(accessManager)); + GuardianModule module = new GuardianModule(sessionRegistry, guardians, threshold, address(accessManager)); GuardiansDeployment memory deployment; deployment.accessManager = address(accessManager); deployment.guardianModule = address(module); - deployment.workloadVerifier = address(workloadVerifier); + deployment.sessionRegistry = address(sessionRegistry); return deployment; } diff --git a/mainnet-contracts/script/DeployPuffer.s.sol b/mainnet-contracts/script/DeployPuffer.s.sol index 70f1227e..63fa269c 100644 --- a/mainnet-contracts/script/DeployPuffer.s.sol +++ b/mainnet-contracts/script/DeployPuffer.s.sol @@ -200,7 +200,7 @@ contract DeployPuffer is BaseScript { vm.label(address(pufferProtocolImpl), "PufferProtocolImplementation"); vm.label(address(moduleManagerProxy), "PufferModuleManager"); vm.label(address(pufferModuleBeacon), "PufferModuleBeacon"); - vm.label(address(guardiansDeployment.workloadVerifier), "WorkloadVerifier"); + vm.label(address(guardiansDeployment.sessionRegistry), "SessionRegistry"); // return (pufferProtocol, pool, accessManager); return PufferProtocolDeployment({ @@ -210,7 +210,7 @@ contract DeployPuffer is BaseScript { pufferProtocol: address(proxy), guardianModule: guardiansDeployment.guardianModule, accessManager: guardiansDeployment.accessManager, - workloadVerifier: guardiansDeployment.workloadVerifier, + sessionRegistry: guardiansDeployment.sessionRegistry, beacon: address(pufferModuleBeacon), restakingOperatorBeacon: address(restakingOperatorBeacon), moduleManager: address(moduleManagerProxy), diff --git a/mainnet-contracts/script/DeploymentStructs.sol b/mainnet-contracts/script/DeploymentStructs.sol index 3c826b07..e15dd09c 100644 --- a/mainnet-contracts/script/DeploymentStructs.sol +++ b/mainnet-contracts/script/DeploymentStructs.sol @@ -7,7 +7,7 @@ pragma solidity >=0.8.0 <0.9.0; struct GuardiansDeployment { address accessManager; address guardianModule; - address workloadVerifier; + address sessionRegistry; } /** @@ -18,7 +18,7 @@ struct PufferProtocolDeployment { address pufferProtocol; address guardianModule; address accessManager; - address workloadVerifier; + address sessionRegistry; address beacon; // Beacon for Puffer modules address restakingOperatorBeacon; // Beacon for Restaking Operator address moduleManager; diff --git a/mainnet-contracts/script/GenerateBLSKeysAndRegisterValidators.s.sol b/mainnet-contracts/script/GenerateBLSKeysAndRegisterValidators.s.sol index 414e4f96..62e2945d 100644 --- a/mainnet-contracts/script/GenerateBLSKeysAndRegisterValidators.s.sol +++ b/mainnet-contracts/script/GenerateBLSKeysAndRegisterValidators.s.sol @@ -174,7 +174,9 @@ contract GenerateBLSKeysAndRegisterValidators is Script { // Generates a new validator key using coral https://github.com/PufferFinance/coral/tree/main function _generateValidatorKey(uint256 idx, bytes32 moduleName) internal { uint256 numberOfGuardians = pufferProtocol.GUARDIAN_MODULE().getGuardians().length; - bytes[] memory guardianPubKeys = pufferProtocol.GUARDIAN_MODULE().getGuardiansEnclavePubkeys(); + // bytes[] memory guardianPubKeys = pufferProtocol.GUARDIAN_MODULE().getGuardiansEnclavePubkeys(); // This is now deprecated + //TODO Update this if needed + bytes[] memory guardianPubKeys = new bytes[](numberOfGuardians); address moduleAddress = IPufferProtocol(protocolAddress).getModuleAddress(moduleName); bytes memory withdrawalCredentials = IPufferProtocol(protocolAddress).getWithdrawalCredentials(moduleAddress); diff --git a/mainnet-contracts/script/SetupAccess.s.sol b/mainnet-contracts/script/SetupAccess.s.sol index 84f66220..cbbda217 100644 --- a/mainnet-contracts/script/SetupAccess.s.sol +++ b/mainnet-contracts/script/SetupAccess.s.sol @@ -267,13 +267,12 @@ contract SetupAccess is BaseScript { } function _setupGuardianModuleRoles() internal view returns (bytes memory) { - bytes4[] memory selectors = new bytes4[](6); - selectors[0] = GuardianModule.registerGoldenMeasurement.selector; - selectors[1] = GuardianModule.deregisterGoldenMeasurement.selector; - selectors[2] = GuardianModule.addGuardian.selector; - selectors[3] = GuardianModule.removeGuardian.selector; - selectors[4] = GuardianModule.setEjectionThreshold.selector; - selectors[5] = GuardianModule.setThreshold.selector; + bytes4[] memory selectors = new bytes4[](5); + selectors[0] = GuardianModule.setAllowedWorkload.selector; + selectors[1] = GuardianModule.addGuardian.selector; + selectors[2] = GuardianModule.removeGuardian.selector; + selectors[3] = GuardianModule.setEjectionThreshold.selector; + selectors[4] = GuardianModule.setThreshold.selector; return abi.encodeWithSelector( AccessManager.setTargetFunctionRole.selector, pufferDeployment.guardianModule, selectors, ROLE_ID_DAO diff --git a/mainnet-contracts/src/GuardianModule.sol b/mainnet-contracts/src/GuardianModule.sol index d4c56ac7..e6c7ede5 100644 --- a/mainnet-contracts/src/GuardianModule.sol +++ b/mainnet-contracts/src/GuardianModule.sol @@ -2,7 +2,7 @@ pragma solidity >=0.8.0 <0.9.0; import { AccessManaged } from "@openzeppelin/contracts/access/manager/AccessManaged.sol"; -import { IGuardianModule } from "./interface/IGuardianModule.sol"; +import { IGuardianModule, GuardianSessionProof } from "./interface/IGuardianModule.sol"; import { Unauthorized, InvalidAddress } from "./Errors.sol"; import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import { MessageHashUtils } from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; @@ -11,6 +11,8 @@ import { LibGuardianMessages } from "./LibGuardianMessages.sol"; import { Address } from "@openzeppelin/contracts/utils/Address.sol"; import { StoppedValidatorInfo } from "./struct/StoppedValidatorInfo.sol"; import { ISessionRegistry, PublicIdentity, CVMSession } from "@automata-network/automata-tee-workload-measurement/interfaces/registries/ISessionRegistry.sol"; +import { LibKey } from "@automata-network/automata-tee-workload-measurement/lib/LibKey.sol"; +import { ALGO_ID_ES256K } from "@automata-network/automata-tee-workload-measurement/types/Constants.sol"; /** * @title Guardian module @@ -55,22 +57,6 @@ contract GuardianModule is AccessManaged, IGuardianModule { */ uint256 internal _ejectionThreshold; - /** - * @dev Enclave data - * The guardian doesn't know the Secret Key of an enclave wallet - */ - struct GuardianData { - uint256 nonce; - bytes enclavePubKey; - address enclaveAddress; - } - - /** - * @dev Mapping of a Guardian's fingerprint to enclave data - */ - mapping(bytes32 ownerFingerprint => GuardianData data) - internal _guardianEnclaves; - /** * @dev Mapping of allowed workload IDs (can be added/removed) */ @@ -148,7 +134,7 @@ contract GuardianModule is AccessManaged, IGuardianModule { bytes calldata signature, bytes calldata withdrawalCredentials, bytes32 depositDataRoot, - bytes[] calldata enclaveSignatures + GuardianSessionProof[] calldata guardianProofs ) external view { // Recreate the message hash bytes32 signedMessageHash = LibGuardianMessages @@ -160,13 +146,11 @@ contract GuardianModule is AccessManaged, IGuardianModule { depositDataRoot: depositDataRoot }); - // Check the signatures - bool validSignatures = validateGuardiansEnclaveSignatures({ - enclaveSignatures: enclaveSignatures, - signedMessageHash: signedMessageHash - }); - - if (!validSignatures) { + bool validSessionProofs = validateSessionProofs( + guardianProofs, + signedMessageHash + ); + if (!validSessionProofs) { revert Unauthorized(); } } @@ -236,16 +220,80 @@ contract GuardianModule is AccessManaged, IGuardianModule { /** * @inheritdoc IGuardianModule */ - function validateGuardiansEnclaveSignatures( - bytes[] calldata enclaveSignatures, + function validateSessionProofs( + GuardianSessionProof[] calldata guardianProofs, bytes32 signedMessageHash ) public view returns (bool) { - return - _validateSignatures( - getGuardiansEnclaveAddresses(), - enclaveSignatures, - signedMessageHash + uint256 threshold = _threshold; + uint256 proofsLen = guardianProofs.length; + require(proofsLen >= threshold, Unauthorized()); + + uint256 validSignatures; + address[] memory seen = new address[](proofsLen); + + for (uint256 i; i < proofsLen; ++i) { + address guardian = _verifyGuardianSession( + guardianProofs[i].sessionId, + guardianProofs[i].sessionKey, + guardianProofs[i].ownerKey, + signedMessageHash, + guardianProofs[i].signature ); + + bool duplicate; + for (uint256 j; j < validSignatures; ++j) { + if (seen[j] == guardian) { + duplicate = true; + break; + } + } + if (duplicate) continue; + + seen[validSignatures] = guardian; + ++validSignatures; + } + + return validSignatures >= threshold; + } + + /** + * @dev Verifies a TEE session signature, validates the session owner, and checks workload. + * @param sessionId The session id to verify against + * @param sessionKey The session's public key + * @param ownerKey The owner's public key (must be ES256K, 65 bytes) + * @param signedMessageHash The message hash that was signed + * @param signature The signature to verify + * @return guardian The guardian address derived from ownerKey + */ + function _verifyGuardianSession( + bytes32 sessionId, + PublicIdentity calldata sessionKey, + PublicIdentity calldata ownerKey, + bytes32 signedMessageHash, + bytes calldata signature + ) internal view returns (address guardian) { + require(ownerKey.typeId == ALGO_ID_ES256K, InvalidECDSAPubKey()); + require(ownerKey.key.length == _ECDSA_KEY_LENGTH, InvalidECDSAPubKey()); + + guardian = address(uint160(uint256(keccak256(ownerKey.key[1:])))); + require(_guardians.contains(guardian), Unauthorized()); + + bool valid = SESSION_REGISTRY.verifySessionSignature( + sessionId, + sessionKey, + signedMessageHash, + signature + ); + require(valid, InvalidSignature()); + + bytes32 ownerFingerprint = SESSION_REGISTRY.getSessionOwner(sessionId); + require( + ownerFingerprint == LibKey.computeKeyFingerprint(ownerKey), + InvalidECDSAPubKey() + ); + + CVMSession memory session = SESSION_REGISTRY.getSession(sessionId); + require(_allowedWorkloads[session.workloadId], WorkloadNotAllowed()); } /** @@ -260,7 +308,10 @@ contract GuardianModule is AccessManaged, IGuardianModule { * @inheritdoc IGuardianModule * @dev Restricted to the DAO */ - function setAllowedWorkload(bytes32 workloadId, bool allowed) external restricted { + function setAllowedWorkload( + bytes32 workloadId, + bool allowed + ) external restricted { _allowedWorkloads[workloadId] = allowed; emit WorkloadAllowanceChanged(workloadId, allowed); } @@ -313,63 +364,6 @@ contract GuardianModule is AccessManaged, IGuardianModule { return _guardians.values(); } - /** - * @inheritdoc IGuardianModule - */ - function rotateGuardianKey( - bytes32 sessionId, - PublicIdentity calldata sessionKey, - uint256 nonce, - bytes calldata pubKey, - bytes calldata signature - ) external { - // Build rotation message (replay protection) - bytes32 rotationMessage = keccak256( - abi.encode( - "ROTATE_GUARDIAN_KEY", - nonce, - pubKey, - block.chainid, - address(this) - ) - ); - bool valid = SESSION_REGISTRY.verifySessionSignature( - sessionId, - sessionKey, - rotationMessage, - signature - ); - require(valid, InvalidSignature()); - // Signature verified: session is active and signature is valid - - bytes32 ownerFingerprint = SESSION_REGISTRY.getSessionOwner(sessionId); - - // Optional: Get more context via SESSION_REGISTRY.getSession(sessionId) - // Returns CVMSession with: - // - workloadId: registered workload identifier - // - baseImageId: trusted base image identifier - // - platformProfileId: TEE platform (e.g., "gcp-tdx", "azure-snp") - // - variantId: machineType variant - // Compare session.workloadId with allowedWorkloads mapping - CVMSession memory session = SESSION_REGISTRY.getSession(sessionId); - require(_allowedWorkloads[session.workloadId], WorkloadNotAllowed()); - - // Verify nonce for replay protection (starts at 0 for new guardians) - GuardianData storage stored = _guardianEnclaves[ownerFingerprint]; - require(stored.nonce == nonce, InvalidNonce()); - - address computedAddress = address( - uint160(uint256(keccak256(pubKey[1:]))) - ); - - // Update guardian's enclave data - stored.enclavePubKey = pubKey; - stored.nonce += 1; - stored.enclaveAddress = computedAddress; - - emit RotatedGuardianKey(ownerFingerprint, computedAddress); - } - /** * @inheritdoc IGuardianModule */ @@ -377,58 +371,6 @@ contract GuardianModule is AccessManaged, IGuardianModule { return _ejectionThreshold; } - /** - * @inheritdoc IGuardianModule - */ - function getGuardiansEnclaveAddress( - address guardian - ) external view returns (address) { - return _guardianEnclaves[guardian].enclaveAddress; - } - - /** - * @inheritdoc IGuardianModule - */ - function getGuardiansEnclaveAddresses() - public - view - returns (address[] memory) - { - uint256 guardiansLength = _guardians.length(); - address[] memory enclaveAddresses = new address[](guardiansLength); - - for (uint256 i; i < guardiansLength; ++i) { - // If the guardian doesn't have an enclave address, we use `0xdead` address - // The reason for this is that we use .tryRecover in signature verification, and a valid signature can be crafted to recover to address(0) - address enclaveAddress = _guardianEnclaves[_guardians.at(i)] - .enclaveAddress == address(0) - ? address(0x000000000000000000000000000000000000dEaD) - : _guardianEnclaves[_guardians.at(i)].enclaveAddress; - enclaveAddresses[i] = enclaveAddress; - } - - return enclaveAddresses; - } - - /** - * @inheritdoc IGuardianModule - */ - function getGuardiansEnclavePubkeys() - external - view - returns (bytes[] memory) - { - uint256 guardiansLength = _guardians.length(); - bytes[] memory enclavePubkeys = new bytes[](guardiansLength); - - for (uint256 i; i < guardiansLength; ++i) { - enclavePubkeys[i] = _guardianEnclaves[_guardians.at(i)] - .enclavePubKey; - } - - return enclavePubkeys; - } - /** * @inheritdoc IGuardianModule */ @@ -504,4 +446,5 @@ contract GuardianModule is AccessManaged, IGuardianModule { return validSignatures < _threshold ? false : true; } + } diff --git a/mainnet-contracts/src/PufferProtocol.sol b/mainnet-contracts/src/PufferProtocol.sol index d910547e..cf3b4080 100644 --- a/mainnet-contracts/src/PufferProtocol.sol +++ b/mainnet-contracts/src/PufferProtocol.sol @@ -8,7 +8,7 @@ import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils import { PufferProtocolStorage } from "./PufferProtocolStorage.sol"; import { PufferModuleManager } from "./PufferModuleManager.sol"; import { IPufferOracleV2 } from "./interface/IPufferOracleV2.sol"; -import { IGuardianModule } from "./interface/IGuardianModule.sol"; +import { IGuardianModule, GuardianSessionProof } from "./interface/IGuardianModule.sol"; import { IBeaconDepositContract } from "./interface/IBeaconDepositContract.sol"; import { ValidatorKeyData } from "./struct/ValidatorKeyData.sol"; import { Validator } from "./struct/Validator.sol"; @@ -252,7 +252,7 @@ contract PufferProtocol is IPufferProtocol, AccessManagedUpgradeable, UUPSUpgrad * @dev Restricted to Puffer Paymaster */ function provisionNode( - bytes[] calldata guardianEnclaveSignatures, + GuardianSessionProof[] calldata guardianProofs, bytes calldata validatorSignature, bytes32 depositRootHash ) external restricted { @@ -275,7 +275,7 @@ contract PufferProtocol is IPufferProtocol, AccessManagedUpgradeable, UUPSUpgrad $: $, moduleName: moduleName, index: index, - guardianEnclaveSignatures: guardianEnclaveSignatures, + guardianProofs: guardianProofs, validatorSignature: validatorSignature }); @@ -615,17 +615,16 @@ contract PufferProtocol is IPufferProtocol, AccessManagedUpgradeable, UUPSUpgrad function getPayload(bytes32 moduleName, bool usingEnclave) external view - returns (bytes[] memory, bytes memory, uint256, uint256) + returns (bytes memory, uint256, uint256) { ProtocolStorage storage $ = _getPufferProtocolStorage(); - bytes[] memory pubKeys = GUARDIAN_MODULE.getGuardiansEnclavePubkeys(); bytes memory withdrawalCredentials = getWithdrawalCredentials(address($.modules[moduleName])); uint256 threshold = GUARDIAN_MODULE.getThreshold(); uint256 validatorBond = usingEnclave ? _ENCLAVE_VALIDATOR_BOND : _NO_ENCLAVE_VALIDATOR_BOND; uint256 ethAmount = validatorBond + ($.minimumVtAmount * PUFFER_ORACLE.getValidatorTicketPrice()) / 1 ether; - return (pubKeys, withdrawalCredentials, threshold, ethAmount); + return (withdrawalCredentials, threshold, ethAmount); } /** @@ -770,7 +769,7 @@ contract PufferProtocol is IPufferProtocol, AccessManagedUpgradeable, UUPSUpgrad ProtocolStorage storage $, bytes32 moduleName, uint256 index, - bytes[] calldata guardianEnclaveSignatures, + GuardianSessionProof[] calldata guardianProofs, bytes calldata validatorSignature ) internal { bytes memory validatorPubKey = $.validators[moduleName][index].pubKey; @@ -787,7 +786,7 @@ contract PufferProtocol is IPufferProtocol, AccessManagedUpgradeable, UUPSUpgrad signature: validatorSignature, depositDataRoot: depositDataRoot, withdrawalCredentials: withdrawalCredentials, - guardianEnclaveSignatures: guardianEnclaveSignatures + guardianProofs: guardianProofs }); PufferModule module = $.modules[moduleName]; diff --git a/mainnet-contracts/src/interface/IGuardianModule.sol b/mainnet-contracts/src/interface/IGuardianModule.sol index 84219333..b359269e 100644 --- a/mainnet-contracts/src/interface/IGuardianModule.sol +++ b/mainnet-contracts/src/interface/IGuardianModule.sol @@ -4,6 +4,13 @@ pragma solidity >=0.8.0 <0.9.0; import { StoppedValidatorInfo } from "../struct/StoppedValidatorInfo.sol"; import { PublicIdentity } from "@automata-network/automata-tee-workload-measurement/types/Common.sol"; +struct GuardianSessionProof { + bytes32 sessionId; + PublicIdentity sessionKey; + PublicIdentity ownerKey; + bytes signature; +} + /** * @title IGuardianModule interface * @author Puffer Finance @@ -103,12 +110,6 @@ interface IGuardianModule { */ event WorkloadAllowanceChanged(bytes32 workloadId, bool allowed); - - /** - * @notice Returns the enclave address registered to `guardian` - */ - function getGuardiansEnclaveAddress(address guardian) external view returns (address); - /** * @notice Returns the ejection threshold ETH value * @dev The ejection threshold is the minimum amount of ETH on the beacon chain required do the validation duties @@ -156,7 +157,7 @@ interface IGuardianModule { * @param signature The signature * @param withdrawalCredentials The withdrawal credentials * @param depositDataRoot The deposit data root - * @param guardianEnclaveSignatures The guardian enclave signatures + * @param guardianProofs The guardian session proofs */ function validateProvisionNode( uint256 pufferModuleIndex, @@ -164,7 +165,7 @@ interface IGuardianModule { bytes calldata signature, bytes calldata withdrawalCredentials, bytes32 depositDataRoot, - bytes[] calldata guardianEnclaveSignatures + GuardianSessionProof[] calldata guardianProofs ) external view; /** @@ -219,17 +220,6 @@ interface IGuardianModule { */ function setEjectionThreshold(uint256 newThreshold) external; - /** - * @dev Validates the signatures of the guardians' enclave signatures - * @param enclaveSignatures The array of enclave signatures - * @param signedMessageHash The hash of the signed message - * @return A boolean indicating whether the signatures are valid - */ - function validateGuardiansEnclaveSignatures(bytes[] calldata enclaveSignatures, bytes32 signedMessageHash) - external - view - returns (bool); - /** * @dev Validates the signatures of the guardians' EOAs. * @param eoaSignatures The array of EOAs' signatures. @@ -242,32 +232,17 @@ interface IGuardianModule { returns (bool); /** - * @notice Rotates guardian's key - * @dev Guardian = session owner (NOT msg.sender) - * Uses nonce for replay protection (starts at 0 for new guardians) - * @param sessionId is the session id of the guardian - * @param sessionKey is the session key of the guardian - * @param nonce is the nonce for replay protection - * @param pubKey is the public key of the new signature - * @param signature is the signature to verify - */ - function rotateGuardianKey( - bytes32 sessionId, - PublicIdentity calldata sessionKey, - uint256 nonce, - bytes calldata pubKey, - bytes calldata signature - ) external; - - /** - * @notice Returns the guardians enclave addresses - */ - function getGuardiansEnclaveAddresses() external view returns (address[] memory); - - /** - * @notice Returns the guardians enclave public keys + * @dev Validates an array of guardian session proofs against a message hash. + * Verifies each proof via SessionRegistry (including workload), prevents duplicate + * guardian counting, and requires at least `_threshold` unique valid guardian proofs. + * @param guardianProofs The array of guardian session proofs + * @param signedMessageHash The message hash that was signed + * @return A boolean indicating whether the session proofs are valid and meet the threshold requirement */ - function getGuardiansEnclavePubkeys() external view returns (bytes[] memory); + function validateSessionProofs( + GuardianSessionProof[] calldata guardianProofs, + bytes32 signedMessageHash + )external view returns (bool); /** * @notice Checks if an account is a guardian diff --git a/mainnet-contracts/src/interface/IPufferProtocol.sol b/mainnet-contracts/src/interface/IPufferProtocol.sol index f6a87a69..4d0fec0f 100644 --- a/mainnet-contracts/src/interface/IPufferProtocol.sol +++ b/mainnet-contracts/src/interface/IPufferProtocol.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.0 <0.9.0; import { Validator } from "../struct/Validator.sol"; import { ValidatorKeyData } from "../struct/ValidatorKeyData.sol"; -import { IGuardianModule } from "../interface/IGuardianModule.sol"; +import { IGuardianModule, GuardianSessionProof } from "../interface/IGuardianModule.sol"; import { PufferModuleManager } from "../PufferModuleManager.sol"; import { PufferVaultV5 } from "../PufferVaultV5.sol"; import { IPufferOracleV2 } from "../interface/IPufferOracleV2.sol"; @@ -282,7 +282,7 @@ interface IPufferProtocol { * @dev You can check who is next for provisioning by calling `getNextValidatorToProvision` method */ function provisionNode( - bytes[] calldata guardianEnclaveSignatures, + GuardianSessionProof[] calldata guardianPro, bytes calldata validatorSignature, bytes32 depositRootHash ) external; diff --git a/mainnet-contracts/test/helpers/IntegrationTestHelper.sol b/mainnet-contracts/test/helpers/IntegrationTestHelper.sol index 6cde8427..8d6f7541 100644 --- a/mainnet-contracts/test/helpers/IntegrationTestHelper.sol +++ b/mainnet-contracts/test/helpers/IntegrationTestHelper.sol @@ -10,7 +10,7 @@ import { PufferModuleManager } from "../../src/PufferModuleManager.sol"; import { UpgradeableBeacon } from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; import { DeployEverything } from "script/DeployEverything.s.sol"; import { AccessManager } from "@openzeppelin/contracts/access/manager/AccessManager.sol"; -import { IWorkloadVerifier } from "@automata-network/automata-tee-workload-measurement/interfaces/IWorkloadVerifier.sol"; +import { ISessionRegistry } from "@automata-network/automata-tee-workload-measurement/interfaces/registries/ISessionRegistry.sol"; contract IntegrationTestHelper is Test { address DAO = 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; @@ -22,11 +22,11 @@ contract IntegrationTestHelper is Test { AccessManager public accessManager; - IWorkloadVerifier public verifier; + ISessionRegistry public sessionRegistry; bytes32 PUFFER_MODULE_0 = bytes32("PUFFER_MODULE_0"); address PAYMASTER = 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; - address WORKLOAD_VERIFIER = address(0); //TODO [TDX] Set the address of the workload verifier + address SESSION_REGISTRY = address(0); //TODO [TDX] Set the address of the session registry // custom block number function deployContractsHoodi(uint256 blockNumber) public virtual { @@ -51,14 +51,14 @@ contract IntegrationTestHelper is Test { function _deployAndLabel(address[] memory guardians, uint256 threshold) internal { // Deploy everything with one script (PufferProtocolDeployment memory pufferDeployment,) = - new DeployEverything().run(WORKLOAD_VERIFIER, guardians, threshold, PAYMASTER); + new DeployEverything().run(SESSION_REGISTRY, guardians, threshold, PAYMASTER); pufferProtocol = PufferProtocol(payable(pufferDeployment.pufferProtocol)); vm.label(address(pufferProtocol), "PufferProtocol"); accessManager = AccessManager(pufferDeployment.accessManager); vm.label(address(accessManager), "AccessManager"); - verifier = IWorkloadVerifier(pufferDeployment.workloadVerifier); - vm.label(address(verifier), "WorkloadVerifier"); + sessionRegistry = ISessionRegistry(pufferDeployment.sessionRegistry); + vm.label(address(sessionRegistry), "SessionRegistry"); guardianModule = GuardianModule(payable(pufferDeployment.guardianModule)); vm.label(address(guardianModule), "GuardianModule"); beacon = UpgradeableBeacon(pufferDeployment.beacon); diff --git a/mainnet-contracts/test/helpers/UnitTestHelper.sol b/mainnet-contracts/test/helpers/UnitTestHelper.sol index 23e7a6c7..8d1dac05 100644 --- a/mainnet-contracts/test/helpers/UnitTestHelper.sol +++ b/mainnet-contracts/test/helpers/UnitTestHelper.sol @@ -13,15 +13,16 @@ import { IGuardianModule } from "../../src/interface/IGuardianModule.sol"; import { UpgradeableBeacon } from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; import { DeployEverything } from "../../script/DeployEverything.s.sol"; import { PufferProtocolDeployment, BridgingDeployment } from "../../script/DeploymentStructs.sol"; -import { - IWorkloadVerifier, - TEEType, - CloudType, - WorkloadCollaterals -} from "@automata-network/automata-tee-workload-measurement/interfaces/IWorkloadVerifier.sol"; -import { TeeReportType } from "@automata-network/automata-tee-workload-measurement/lib/LibTEE.sol"; -import { MeasureablePcr } from "@automata-network/automata-tpm-attestation/interfaces/ITpmAttestation.sol"; -import { GoldenMeasurementInfo, TdxRegistrationData } from "../../src/struct/GuardianModuleStructs.sol"; +// import { +// IWorkloadVerifier, +// TEEType, +// CloudType, +// WorkloadCollaterals +// } from "@automata-network/automata-tee-workload-measurement/interfaces/IWorkloadVerifier.sol"; +// import { TeeReportType } from "@automata-network/automata-tee-workload-measurement/lib/LibTEE.sol"; +// import { MeasureablePcr } from "@automata-network/automata-tpm-attestation/interfaces/ITpmAttestation.sol"; +// import { GoldenMeasurementInfo, TdxRegistrationData } from "../../src/struct/GuardianModuleStructs.sol"; +import { ISessionRegistry } from "@automata-network/automata-tee-workload-measurement/interfaces/registries/ISessionRegistry.sol"; import { AccessManager } from "@openzeppelin/contracts/access/manager/AccessManager.sol"; import { Permit } from "../../src/structs/Permit.sol"; import { PufferDepositor } from "../../src/PufferDepositor.sol"; @@ -43,7 +44,7 @@ import { ROLE_ID_LOCKBOX } from "../../script/Roles.sol"; import { GenerateSlashingELCalldata } from "../../script/AccessManagerMigrations/07_GenerateSlashingELCalldata.s.sol"; -import { WorkloadVerifierMock } from "../mocks/WorkloadVerifierMock.sol"; +import { SessionRegistryMock } from "../mocks/SessionRegistryMock.sol"; contract UnitTestHelper is Test, BaseScript { bytes32 private constant _PERMIT_TYPEHASH = @@ -108,7 +109,7 @@ contract UnitTestHelper is Test, BaseScript { GuardianModule public guardianModule; AccessManager public accessManager; - IWorkloadVerifier public verifier; + ISessionRegistry public sessionRegistry; OperationsCoordinator public operationsCoordinator; AVSContractsRegistry public avsContractsRegistry; RestakingOperatorController public restakingOperatorController; @@ -179,7 +180,7 @@ contract UnitTestHelper is Test, BaseScript { fuzzedAddressMapping[ADDRESS_ZERO] = true; fuzzedAddressMapping[ADDRESS_ONE] = true; fuzzedAddressMapping[address(guardianModule)] = true; - fuzzedAddressMapping[address(verifier)] = true; + fuzzedAddressMapping[address(sessionRegistry)] = true; fuzzedAddressMapping[address(accessManager)] = true; fuzzedAddressMapping[address(beacon)] = true; fuzzedAddressMapping[address(pufferProtocol)] = true; @@ -208,19 +209,19 @@ contract UnitTestHelper is Test, BaseScript { guardians[1] = guardian2; guardians[2] = guardian3; - WorkloadVerifierMock workloadVerifierMock = new WorkloadVerifierMock(); + SessionRegistryMock sessionRegistryMock = new SessionRegistryMock(); // Deploy everything with one script PufferProtocolDeployment memory pufferDeployment; BridgingDeployment memory bridgingDeployment; (pufferDeployment, bridgingDeployment) = - new DeployEverything().run(address(workloadVerifierMock), guardians, 1, PAYMASTER); + new DeployEverything().run(address(sessionRegistryMock), guardians, 1, PAYMASTER); pufferProtocol = PufferProtocol(payable(pufferDeployment.pufferProtocol)); accessManager = AccessManager(pufferDeployment.accessManager); timelock = pufferDeployment.timelock; - verifier = IWorkloadVerifier(pufferDeployment.workloadVerifier); + sessionRegistry = ISessionRegistry(pufferDeployment.sessionRegistry); guardianModule = GuardianModule(payable(pufferDeployment.guardianModule)); beacon = UpgradeableBeacon(pufferDeployment.beacon); pufferModuleManager = PufferModuleManager(payable(pufferDeployment.moduleManager)); @@ -253,101 +254,8 @@ contract UnitTestHelper is Test, BaseScript { vm.label(address(pufferDepositor), "PufferDepositor"); vm.label(address(pufferProtocol), "PufferProtocol"); - // Register Golden Measurement for TDX - vm.startPrank(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266); - // Grant DAO role to DAO address - accessManager.grantRole(ROLE_ID_DAO, DAO, 0); - // Set up registerGoldenMeasurement function to require DAO role - bytes4[] memory guardianModuleSelectors = new bytes4[](1); - guardianModuleSelectors[0] = GuardianModule.registerGoldenMeasurement.selector; - accessManager.setTargetFunctionRole(address(guardianModule), guardianModuleSelectors, ROLE_ID_DAO); - vm.stopPrank(); - - // Register a test golden measurement - bytes32 testMeasurementHash = keccak256("test-golden-measurement"); - vm.startPrank(DAO); - guardianModule.registerGoldenMeasurement( - testMeasurementHash, - GoldenMeasurementInfo({ - valid: true, - teeType: TEEType.IntelTDX, - cloudType: CloudType.GCP, - tag: "test-v1.0.0" - }) - ); - - workloadVerifierMock.setMeasurementHash(testMeasurementHash); - vm.stopPrank(); - - assertEq( - blockhash(block.number), - hex"0000000000000000000000000000000000000000000000000000000000000000", - "bad blockhash" - ); - - // Register enclave keys for guardians - vm.startPrank(guardians[0]); - vm.expectEmit(true, true, true, true); - emit IGuardianModule.RotatedGuardianKey(guardians[0], guardian1Enclave, guardian1EnclavePubKey); - guardianModule.rotateGuardianKey( - 0, - guardian1EnclavePubKey, - TdxRegistrationData({ - teeType: TEEType.IntelTDX, - teeReportType: TeeReportType.Solidity, - cloudType: CloudType.GCP, - teeAttestationReport: abi.encodePacked( - keccak256(abi.encodePacked(guardian1EnclavePubKey, blockhash(block.number))) - ), - workloadCollaterals: _createEmptyWorkloadCollaterals() - }) - ); - vm.stopPrank(); - - vm.startPrank(guardians[1]); - vm.expectEmit(true, true, true, true); - emit IGuardianModule.RotatedGuardianKey(guardians[1], guardian2Enclave, guardian2EnclavePubKey); - guardianModule.rotateGuardianKey( - 1, - guardian2EnclavePubKey, - TdxRegistrationData({ - teeType: TEEType.IntelTDX, - teeReportType: TeeReportType.Solidity, - cloudType: CloudType.GCP, - teeAttestationReport: abi.encodePacked( - keccak256(abi.encodePacked(guardian2EnclavePubKey, blockhash(block.number))) - ), - workloadCollaterals: _createEmptyWorkloadCollaterals() - }) - ); - vm.stopPrank(); - - vm.startPrank(guardians[2]); - vm.expectEmit(true, true, true, true); - emit IGuardianModule.RotatedGuardianKey(guardians[2], guardian3Enclave, guardian3EnclavePubKey); - guardianModule.rotateGuardianKey( - 2, - guardian3EnclavePubKey, - TdxRegistrationData({ - teeType: TEEType.IntelTDX, - teeReportType: TeeReportType.Solidity, - cloudType: CloudType.GCP, - teeAttestationReport: abi.encodePacked( - keccak256(abi.encodePacked(guardian3EnclavePubKey, blockhash(block.number))) - ), - workloadCollaterals: _createEmptyWorkloadCollaterals() - }) - ); - vm.stopPrank(); - - assertEq(guardianModule.getGuardiansEnclaveAddress(guardians[0]), guardian1Enclave, "bad enclave address1"); - assertEq(guardianModule.getGuardiansEnclaveAddress(guardians[1]), guardian2Enclave, "bad enclave address2"); - assertEq(guardianModule.getGuardiansEnclaveAddress(guardians[2]), guardian3Enclave, "bad enclave address3"); - - bytes[] memory pubKeys = guardianModule.getGuardiansEnclavePubkeys(); - assertEq(pubKeys[0], guardian1EnclavePubKey, "guardian1 pub key"); - assertEq(pubKeys[1], guardian2EnclavePubKey, "guardian2 pub key"); - assertEq(pubKeys[2], guardian3EnclavePubKey, "guardian3 pub key"); + // No longer enclave adrresses in GuardianModule + // TODO Check if need to config session registry mock } function _upgradePufferVaultToMainnet() internal { @@ -433,14 +341,4 @@ contract UnitTestHelper is Test, BaseScript { t.deadline = deadline; } - function _createEmptyWorkloadCollaterals() internal pure returns (WorkloadCollaterals memory) { - return WorkloadCollaterals({ - tpmQuote: hex"", - tpmSignature: hex"", - pcrs: new MeasureablePcr[](0), - reportId: hex"", - akPub: hex"", - certs: new bytes[](0) - }); - } } diff --git a/mainnet-contracts/test/mocks/SessionRegistryMock.sol b/mainnet-contracts/test/mocks/SessionRegistryMock.sol new file mode 100644 index 00000000..bfec3010 --- /dev/null +++ b/mainnet-contracts/test/mocks/SessionRegistryMock.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.8.0 <0.9.0; + +import {CVMSession, PublicIdentity} from "@automata-network/automata-tee-workload-measurement/interfaces/registries/ISessionRegistry.sol"; + +contract SessionRegistryMock { + + function getSession(bytes32 sessionId) external view returns (CVMSession memory session) { + + } + + function getSessionOwner(bytes32 sessionId) external view returns (bytes32 ownerFingerprint) { + + } + + function verifySessionSignature( + bytes32 sessionId, + PublicIdentity calldata sessionKey, + bytes32 message, + bytes calldata signature + ) external view returns (bool valid) { + + } +} \ No newline at end of file diff --git a/mainnet-contracts/test/mocks/WorkloadVerifierMock.sol b/mainnet-contracts/test/mocks/WorkloadVerifierMock.sol deleted file mode 100644 index 00fc6c3d..00000000 --- a/mainnet-contracts/test/mocks/WorkloadVerifierMock.sol +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity >=0.8.0 <0.9.0; - -import { - TEEType, - TeeReportType, - CloudType, - WorkloadCollaterals -} from "@automata-network/automata-tee-workload-measurement/interfaces/IWorkloadVerifier.sol"; - -contract WorkloadVerifierMock { - bytes32 public mockMeasurementHash; - - function verifyAttestationAndGetMeasurementHash( - TEEType, - TeeReportType, - CloudType, - bytes calldata _teeAttestationReport, - WorkloadCollaterals calldata - ) external payable returns (bytes memory teeOutput, bytes32 measurementHash, bytes memory tpmExtraData) { - return (hex"", mockMeasurementHash, _teeAttestationReport); - } - - function setMeasurementHash(bytes32 _measurementHash) external { - mockMeasurementHash = _measurementHash; - } -} diff --git a/mainnet-contracts/test/unit/GuardianModule.t.sol b/mainnet-contracts/test/unit/GuardianModule.t.sol index 3c7bcda9..83ba256d 100644 --- a/mainnet-contracts/test/unit/GuardianModule.t.sol +++ b/mainnet-contracts/test/unit/GuardianModule.t.sol @@ -4,9 +4,7 @@ pragma solidity >=0.8.0 <0.9.0; import { UnitTestHelper } from "../helpers/UnitTestHelper.sol"; import { IGuardianModule } from "../../src/interface/IGuardianModule.sol"; import { Unauthorized } from "../../src/Errors.sol"; -import { TEEType, TeeReportType, CloudType } from "@automata-network/automata-tee-workload-measurement/lib/LibTEE.sol"; -import { TdxRegistrationData } from "../../src/struct/GuardianModuleStructs.sol"; -import { WorkloadVerifierMock } from "../mocks/WorkloadVerifierMock.sol"; +import { SessionRegistryMock } from "../mocks/SessionRegistryMock.sol"; contract GuardianModuleTest is UnitTestHelper { function setUp() public override { @@ -37,78 +35,6 @@ contract GuardianModuleTest is UnitTestHelper { guardianModule.setThreshold(50); } - function test_rotateGuardianKey_from_non_guardian_reverts() public { - vm.expectRevert(Unauthorized.selector); - guardianModule.rotateGuardianKey( - 0, - new bytes(55), - TdxRegistrationData({ - teeType: TEEType.IntelTDX, - teeReportType: TeeReportType.Solidity, - cloudType: CloudType.GCP, - teeAttestationReport: hex"", - workloadCollaterals: _createEmptyWorkloadCollaterals() - }) - ); - } - - function test_rotateGuardianKey_to_invalid_pubKey_reverts() public { - vm.startPrank(guardian1); - - vm.expectRevert(IGuardianModule.InvalidECDSAPubKey.selector); - guardianModule.rotateGuardianKey( - 0, - new bytes(55), - TdxRegistrationData({ - teeType: TEEType.IntelTDX, - teeReportType: TeeReportType.Solidity, - cloudType: CloudType.GCP, - teeAttestationReport: hex"", - workloadCollaterals: _createEmptyWorkloadCollaterals() - }) - ); - } - - function test_rotateGuardianKey_with_invalid_measurement_reverts() public { - vm.startPrank(guardian1); - - WorkloadVerifierMock(address(verifier)).setMeasurementHash(bytes32("some invalid measurement hash")); - - vm.expectRevert(IGuardianModule.InvalidMeasurement.selector); - guardianModule.rotateGuardianKey( - 0, - guardian3EnclavePubKey, - TdxRegistrationData({ - teeType: TEEType.IntelTDX, - teeReportType: TeeReportType.Solidity, - cloudType: CloudType.GCP, - teeAttestationReport: hex"", - workloadCollaterals: _createEmptyWorkloadCollaterals() - }) - ); - vm.stopPrank(); - } - - function test_rotateGuardianKey_with_invalid_commitment_mismatch() public { - vm.startPrank(guardian1); - - vm.expectRevert(IGuardianModule.CommitmentMismatch.selector); - guardianModule.rotateGuardianKey( - 0, - guardian3EnclavePubKey, - TdxRegistrationData({ - teeType: TEEType.IntelTDX, - teeReportType: TeeReportType.Solidity, - cloudType: CloudType.GCP, - teeAttestationReport: abi.encodePacked( - keccak256(abi.encodePacked(guardian2EnclavePubKey, blockhash(block.number))) - ), - workloadCollaterals: _createEmptyWorkloadCollaterals() - }) - ); - vm.stopPrank(); - } - function test_addGuardian(address guardian) public assumeEOA(guardian) { vm.startPrank(DAO); @@ -128,7 +54,7 @@ contract GuardianModuleTest is UnitTestHelper { guardianModule.removeGuardian(guardian); } - function test_remove_guardian_bellow_threshold() public { + function test_remove_guardian_below_threshold() public { // Our test env has 3 guardians and threshold 1 vm.startPrank(DAO); diff --git a/mainnet-contracts/test/unit/PufferProtocol.t.sol b/mainnet-contracts/test/unit/PufferProtocol.t.sol index bff105a3..9fd63816 100644 --- a/mainnet-contracts/test/unit/PufferProtocol.t.sol +++ b/mainnet-contracts/test/unit/PufferProtocol.t.sol @@ -286,17 +286,6 @@ contract PufferProtocolTest is UnitTestHelper { ); } - function test_get_payload() public view { - (bytes[] memory guardianPubKeys,, uint256 threshold,) = pufferProtocol.getPayload(PUFFER_MODULE_0, false); - - assertEq(guardianPubKeys[0], guardian1EnclavePubKey, "guardian1"); - assertEq(guardianPubKeys[1], guardian2EnclavePubKey, "guardian2"); - assertEq(guardianPubKeys[2], guardian3EnclavePubKey, "guardian3"); - - assertEq(guardianPubKeys.length, 3, "pubkeys len"); - assertEq(threshold, 1, "threshold"); - } - // Try to provision a validator when there is nothing to provision function test_provision_reverts() public { (, uint256 idx) = pufferProtocol.getNextValidatorToProvision(); From ebd098e424abe6afbba9e10ea3d06d2b5b6fe0c5 Mon Sep 17 00:00:00 2001 From: Eladio Date: Fri, 13 Feb 2026 18:49:37 +0100 Subject: [PATCH 22/51] Adapted tests to new signatures, worked of mock (WIP) --- .../test/handlers/PufferProtocolHandler.sol | 49 ++++++-- .../test/mocks/SessionRegistryMock.sol | 22 ++++ .../test/unit/PufferProtocol.t.sol | 112 +++++++++++------- mainnet-contracts/test/unit/Timelock.t.sol | 8 +- 4 files changed, 133 insertions(+), 58 deletions(-) diff --git a/mainnet-contracts/test/handlers/PufferProtocolHandler.sol b/mainnet-contracts/test/handlers/PufferProtocolHandler.sol index 95892bcd..89eb08d6 100644 --- a/mainnet-contracts/test/handlers/PufferProtocolHandler.sol +++ b/mainnet-contracts/test/handlers/PufferProtocolHandler.sol @@ -2,6 +2,7 @@ pragma solidity >=0.8.0 <0.9.0; import { IPufferProtocol } from "../../src/interface/IPufferProtocol.sol"; +import { GuardianSessionProof, PublicIdentity } from "../../src/interface/IGuardianModule.sol"; import { EnumerableMap } from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import { console } from "forge-std/console.sol"; @@ -26,6 +27,7 @@ import { PufferOracleV2 } from "../../src/PufferOracleV2.sol"; import { IWETH } from "../../src/interface/Other/IWETH.sol"; import { PufferVaultV5 } from "../../src/PufferVaultV5.sol"; import { PufferModule } from "../../src/PufferModule.sol"; +import { ALGO_ID_ES256K } from "@automata-network/automata-tee-workload-measurement/types/Constants.sol"; struct ProvisionedValidator { bytes32 moduleName; @@ -41,9 +43,12 @@ contract PufferProtocolHandler is Test { // Guardians are preset for the test environment, and these are the enclave secret keys uint256 guardian1SKEnclave = 81165043675487275545095207072241430673874640255053335052777448899322561824201; address guardian1Enclave = vm.addr(guardian1SKEnclave); + bytes guardian1EnclavePubkey = hex"04caf1f9cd82a1284626d405d285250fd6c4f58c469fda05d7fd4f29318aae38e7ccc6f4eaced74d3e2aa3fc0576093860d3045263c4183d694a39911ee9031c73"; uint256 guardian2SKEnclave = 90480947395980135991870782913815514305328820213706480966227475230529794843518; address guardian2Enclave = vm.addr(guardian2SKEnclave); + bytes guardian2EnclavePubkey = hex"04f050c3ce5d575600af388f41876e2962499a97bc8fcfa4a12adf7e4a486a3be9a1db0efd899c09723f83fe490e8215fd596a5f03c819e28a8b95f3cce6238613"; uint256 guardian3SKEnclave = 56094429399408807348734910221877888701411489680816282162734349635927251229227; + bytes guardian3EnclavePubkey = hex"04a55b152177219971a93a64aafc2d61baeaf86526963caa260e71efa2b865527e0307d7bda85312dd6ff23bcc88f2bf228da6295239f72c31b686c48b7b69cdfd"; UnitTestHelper testhelper; address[] public actors; @@ -500,8 +505,8 @@ contract PufferProtocolHandler is Test { if (validatorData.status == Status.PENDING) { bytes memory sig = _getPubKey(validatorData.pubKeypart); - bytes[] memory signatures = _getGuardianSignatures(sig); - pufferProtocol.provisionNode(signatures, mockValidatorSignature, bytes32(0)); + GuardianSessionProof[] memory guardianProofs = _getGuardianProofs(sig); + pufferProtocol.provisionNode(guardianProofs, mockValidatorSignature, bytes32(0)); ghost_validators_validating.push(ProvisionedValidator({ moduleName: moduleName, idx: nextIdx })); @@ -595,12 +600,12 @@ contract PufferProtocolHandler is Test { } // Copied from PufferProtocol.t.sol - function _getGuardianSignatures(bytes memory pubKey) internal view returns (bytes[] memory) { + function _getGuardianProofs(bytes memory pubKey) internal view returns (GuardianSessionProof[] memory) { (bytes32 moduleName, uint256 pendingIdx) = pufferProtocol.getNextValidatorToProvision(); Validator memory validator = pufferProtocol.getValidatorInfo(moduleName, pendingIdx); // If there is no module return empty byte array if (validator.module == address(0)) { - return new bytes[](0); + return new GuardianSessionProof[](0); } bytes memory withdrawalCredentials = pufferProtocol.getWithdrawalCredentials(validator.module); @@ -616,10 +621,10 @@ contract PufferProtocolHandler is Test { }) ); - return _getGuardianEnclaveSignatures(digest); + return _getGuardianEnclaveProofs(digest); } - function _getGuardianEnclaveSignatures(bytes32 digest) internal view returns (bytes[] memory) { + function _getGuardianEnclaveProofs(bytes32 digest) internal view returns (GuardianSessionProof[] memory) { (uint8 v, bytes32 r, bytes32 s) = vm.sign(guardian1SKEnclave, digest); bytes memory signature1 = abi.encodePacked(r, s, v); // note the order here is different from line above. @@ -629,12 +634,33 @@ contract PufferProtocolHandler is Test { (v, r, s) = vm.sign(guardian3SKEnclave, digest); bytes memory signature3 = abi.encodePacked(r, s, v); // note the order here is different from line above. - bytes[] memory guardianSignatures = new bytes[](3); - guardianSignatures[0] = signature1; - guardianSignatures[1] = signature2; - guardianSignatures[2] = signature3; - return guardianSignatures; + // Pre-computed public keys from makeAddrAndKey() + bytes memory guardian1OwnerPubkey = hex"04af497e622b580acc7e8d961bc7fa69aad88774ea39c838ff5411ac87746eb0d0b157c9e9b6f94d4b58313c7c59c975760b4c640e78d9e466e1a2255359d6e092"; + bytes memory guardian2OwnerPubkey = hex"04169f04b8a0f6c552666fbccf9a73184bb0e2a1fbeb66ee56ca2c3271f9398803cad67262f0987f9ea085771868683b53944d421a081a73cce357275b47f3629f"; + bytes memory guardian3OwnerPubkey = hex"04bcb747c6ce73688d800755ac8715198ca92e7d2f0a828e083e254078c8c652e64f15534685ba90ec89362c8c276df81c7e6a2db9f2f2620d7596d9962171d2fc"; + + GuardianSessionProof[] memory guardianProofs = new GuardianSessionProof[](3); + guardianProofs[0] = GuardianSessionProof({ + sessionId: keccak256("guardian1"), + sessionKey: PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian1EnclavePubkey }), + ownerKey: PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian1OwnerPubkey }), + signature: signature1 + }); + guardianProofs[1] = GuardianSessionProof({ + sessionId: keccak256("guardian2"), + sessionKey: PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian2EnclavePubkey }), + ownerKey: PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian2OwnerPubkey }), + signature: signature2 + }); + guardianProofs[2] = GuardianSessionProof({ + sessionId: keccak256("guardian3"), + sessionKey: PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian3EnclavePubkey }), + ownerKey: PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian3OwnerPubkey }), + signature: signature3 + }); + + return guardianProofs; } function _getGuardianEOASignatures(bytes32 digest) internal returns (bytes[] memory) { @@ -697,4 +723,5 @@ contract PufferProtocolHandler is Test { AccessManager(pufferProtocol.authority()).setTargetFunctionRole(module, selectors, ROLE_ID_PUFFER_PROTOCOL); vm.stopPrank(); } + } diff --git a/mainnet-contracts/test/mocks/SessionRegistryMock.sol b/mainnet-contracts/test/mocks/SessionRegistryMock.sol index bfec3010..2c56f5f4 100644 --- a/mainnet-contracts/test/mocks/SessionRegistryMock.sol +++ b/mainnet-contracts/test/mocks/SessionRegistryMock.sol @@ -2,6 +2,7 @@ pragma solidity >=0.8.0 <0.9.0; import {CVMSession, PublicIdentity} from "@automata-network/automata-tee-workload-measurement/interfaces/registries/ISessionRegistry.sol"; +import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; contract SessionRegistryMock { @@ -19,6 +20,27 @@ contract SessionRegistryMock { bytes32 message, bytes calldata signature ) external view returns (bool valid) { + return _verifySecp256k1(sessionKey.key, message, signature); + } + function _verifySecp256k1(bytes calldata key, bytes32 hash, bytes calldata signature) + internal + pure + returns (bool valid) + { + // Validate key format: must be 65 bytes starting with 0x04 + if (key.length != 65 || key[0] != 0x04) { + return false; + } + + // Derive expected address from public key + // Skip first byte (0x04 prefix) and hash the x,y coordinates + address expectedAddress = address(uint160(uint256(keccak256(key[1:65])))); + + // Recover signer address from signature (using calldata variant to avoid copy) + (address recovered, ECDSA.RecoverError err,) = ECDSA.tryRecover(hash, signature); + + // Valid only if recovery succeeded and address matches + return err == ECDSA.RecoverError.NoError && recovered == expectedAddress; } } \ No newline at end of file diff --git a/mainnet-contracts/test/unit/PufferProtocol.t.sol b/mainnet-contracts/test/unit/PufferProtocol.t.sol index 9fd63816..534f3e65 100644 --- a/mainnet-contracts/test/unit/PufferProtocol.t.sol +++ b/mainnet-contracts/test/unit/PufferProtocol.t.sol @@ -16,6 +16,8 @@ import { LibGuardianMessages } from "../../src/LibGuardianMessages.sol"; import { Permit } from "../../src/structs/Permit.sol"; import { ModuleLimit } from "../../src/struct/ProtocolStorage.sol"; import { StoppedValidatorInfo } from "../../src/struct/StoppedValidatorInfo.sol"; +import { GuardianSessionProof, PublicIdentity } from "../../src/interface/IGuardianModule.sol"; +import { ALGO_ID_ES256K } from "@automata-network/automata-tee-workload-measurement/types/Constants.sol"; contract PufferProtocolTest is UnitTestHelper { using ECDSA for bytes32; @@ -132,11 +134,11 @@ contract PufferProtocolTest is UnitTestHelper { assertEq(moduleName, PUFFER_MODULE_0, "module"); assertEq(idx, 1, "idx should be 1"); - bytes[] memory signatures = _getGuardianSignatures(_getPubKey(bytes32("bob"))); + GuardianSessionProof[] memory guardianProofs = _getGuardianProofs(_getPubKey(bytes32("bob"))); vm.expectEmit(true, true, true, true); emit SuccessfullyProvisioned(_getPubKey(bytes32("bob")), 1, PUFFER_MODULE_0); - pufferProtocol.provisionNode(signatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); moduleSelectionIndex = pufferProtocol.getModuleSelectIndex(); assertEq(moduleSelectionIndex, 1, "module idx changed"); } @@ -292,11 +294,11 @@ contract PufferProtocolTest is UnitTestHelper { assertEq(type(uint256).max, idx, "module"); // Invalid signatures - bytes[] memory signatures = - _getGuardianSignatures(hex"0000000000000000000000000000000000000000000000000000000000000000"); + GuardianSessionProof[] memory guardianProofs = + _getGuardianProofs(hex"0000000000000000000000000000000000000000000000000000"); vm.expectRevert(); // panic - pufferProtocol.provisionNode(signatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); } // If the deposit root is not bytes(0), it must match match the one returned from the beacon contract @@ -304,13 +306,13 @@ contract PufferProtocolTest is UnitTestHelper { _registerValidatorKey(zeroPubKeyPart, PUFFER_MODULE_0); bytes memory validatorSignature = _validatorSignature(); - bytes[] memory guardianSignatures = _getGuardianSignatures(_getPubKey(zeroPubKeyPart)); + GuardianSessionProof[] memory guardianProofs = _getGuardianProofs(_getPubKey(zeroPubKeyPart)); vm.expectRevert(IPufferProtocol.InvalidDepositRootHash.selector); - pufferProtocol.provisionNode(guardianSignatures, validatorSignature, bytes32("badDepositRoot")); // "depositRoot" is hardcoded in the mock + pufferProtocol.provisionNode(guardianProofs, validatorSignature, bytes32("badDepositRoot")); // "depositRoot" is hardcoded in the mock // now it works - pufferProtocol.provisionNode(guardianSignatures, validatorSignature, DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(guardianProofs, validatorSignature, DEFAULT_DEPOSIT_ROOT); } function test_register_multiple_validators_and_skipProvisioning(bytes32 alicePubKeyPart, bytes32 bobPubKeyPart) @@ -347,19 +349,19 @@ contract PufferProtocolTest is UnitTestHelper { assertEq(pufferProtocol.getPendingValidatorIndex(PUFFER_MODULE_0), 5, "next pending validator index"); - bytes[] memory signatures = _getGuardianSignatures(zeroPubKey); + GuardianSessionProof[] memory guardianProofs = _getGuardianProofs(zeroPubKey); // 1. provision zero key vm.expectEmit(true, true, true, true); emit SuccessfullyProvisioned(zeroPubKey, 0, PUFFER_MODULE_0); - pufferProtocol.provisionNode(signatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); - bytes[] memory bobSignatures = _getGuardianSignatures(bobPubKey); + GuardianSessionProof[] memory bobGuardianProofs = _getGuardianProofs(bobPubKey); // Provision Bob that is not zero pubKey vm.expectEmit(true, true, true, true); emit SuccessfullyProvisioned(bobPubKey, 1, PUFFER_MODULE_0); - pufferProtocol.provisionNode(bobSignatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(bobGuardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); Validator memory bobValidator = pufferProtocol.getValidatorInfo(PUFFER_MODULE_0, 1); @@ -367,10 +369,10 @@ contract PufferProtocolTest is UnitTestHelper { pufferProtocol.skipProvisioning(PUFFER_MODULE_0, _getGuardianSignaturesForSkipping()); - signatures = _getGuardianSignatures(zeroPubKey); + guardianProofs = _getGuardianProofs(zeroPubKey); emit SuccessfullyProvisioned(zeroPubKey, 3, PUFFER_MODULE_0); - pufferProtocol.provisionNode(signatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); // Get validators Validator[] memory registeredValidators = pufferProtocol.getValidators(PUFFER_MODULE_0); @@ -416,12 +418,12 @@ contract PufferProtocolTest is UnitTestHelper { assertTrue(nextModule == PUFFER_MODULE_0, "module selection"); assertTrue(nextId == 0, "module selection"); - bytes[] memory signatures = _getGuardianSignatures(_getPubKey(bytes32("bob"))); + GuardianSessionProof[] memory guardianProofs = _getGuardianProofs(_getPubKey(bytes32("bob"))); // Provision Bob that is not zero pubKey vm.expectEmit(true, true, true, true); emit SuccessfullyProvisioned(_getPubKey(bytes32("bob")), 0, PUFFER_MODULE_0); - pufferProtocol.provisionNode(signatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); (nextModule, nextId) = pufferProtocol.getNextValidatorToProvision(); @@ -429,11 +431,11 @@ contract PufferProtocolTest is UnitTestHelper { // Id is zero, because that is the first in this queue assertTrue(nextId == 0, "module id"); - signatures = _getGuardianSignatures(_getPubKey(bytes32("benjamin"))); + guardianProofs = _getGuardianProofs(_getPubKey(bytes32("benjamin"))); vm.expectEmit(true, true, true, true); emit SuccessfullyProvisioned(_getPubKey(bytes32("benjamin")), 0, EIGEN_DA); - pufferProtocol.provisionNode(signatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); (nextModule, nextId) = pufferProtocol.getNextValidatorToProvision(); @@ -453,23 +455,23 @@ contract PufferProtocolTest is UnitTestHelper { assertTrue(nextId == 1, "module id"); // Provisioning of rocky should fail, because jason is next in line - signatures = _getGuardianSignatures(_getPubKey(bytes32("rocky"))); + guardianProofs = _getGuardianProofs(_getPubKey(bytes32("rocky"))); vm.expectRevert(Unauthorized.selector); - pufferProtocol.provisionNode(signatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); - signatures = _getGuardianSignatures(_getPubKey(bytes32("jason"))); + guardianProofs = _getGuardianProofs(_getPubKey(bytes32("jason"))); // Provision Jason - pufferProtocol.provisionNode(signatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); (nextModule, nextId) = pufferProtocol.getNextValidatorToProvision(); - signatures = _getGuardianSignatures(_getPubKey(bytes32("rocky"))); + guardianProofs = _getGuardianProofs(_getPubKey(bytes32("rocky"))); // Rocky is now in line assertTrue(nextModule == CRAZY_GAINS, "module selection"); assertTrue(nextId == 0, "module id"); - pufferProtocol.provisionNode(signatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); (nextModule, nextId) = pufferProtocol.getNextValidatorToProvision(); @@ -480,11 +482,11 @@ contract PufferProtocolTest is UnitTestHelper { pufferProtocol.getNextValidatorToBeProvisionedIndex(PUFFER_MODULE_0), 1, "next idx for no restaking module" ); - signatures = _getGuardianSignatures(_getPubKey(bytes32("alice"))); + guardianProofs = _getGuardianProofs(_getPubKey(bytes32("alice"))); vm.expectEmit(true, true, true, true); emit SuccessfullyProvisioned(_getPubKey(bytes32("alice")), 1, PUFFER_MODULE_0); - pufferProtocol.provisionNode(signatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); } function test_create_puffer_module() public { @@ -744,10 +746,10 @@ contract PufferProtocolTest is UnitTestHelper { vm.deal(address(pufferVault), 100 ether); _registerValidatorKey(bytes32("alice"), PUFFER_MODULE_0); - bytes[] memory guardianSignatures = _getGuardianSignatures(_getPubKey(bytes32("alice"))); + GuardianSessionProof[] memory guardianProofs = _getGuardianProofs(_getPubKey(bytes32("alice"))); // Register and provision Alice // Alice may be an active validator or it can be exited, doesn't matter - pufferProtocol.provisionNode(guardianSignatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); // Register another validator with using the same data _registerValidatorKey(bytes32("alice"), PUFFER_MODULE_0); @@ -755,7 +757,7 @@ contract PufferProtocolTest is UnitTestHelper { // Try to provision it with the original message (replay attack) // It should revert vm.expectRevert(Unauthorized.selector); - pufferProtocol.provisionNode(guardianSignatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); } function test_validator_limit_per_module() external { @@ -805,7 +807,7 @@ contract PufferProtocolTest is UnitTestHelper { vm.warp(startTimestamp); pufferProtocol.provisionNode( - _getGuardianSignatures(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT + _getGuardianProofs(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT ); // Didn't claim the bond yet @@ -1456,7 +1458,7 @@ contract PufferProtocolTest is UnitTestHelper { uint256 startTimestamp = 1707411226; vm.warp(startTimestamp); pufferProtocol.provisionNode( - _getGuardianSignatures(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT + _getGuardianProofs(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT ); // Give funds to modules @@ -1510,7 +1512,7 @@ contract PufferProtocolTest is UnitTestHelper { uint256 startTimestamp = 1707411226; vm.warp(startTimestamp); pufferProtocol.provisionNode( - _getGuardianSignatures(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT + _getGuardianProofs(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT ); vm.deal(NoRestakingModule, 200 ether); @@ -1562,7 +1564,7 @@ contract PufferProtocolTest is UnitTestHelper { uint256 startTimestamp = 1707411226; vm.warp(startTimestamp); pufferProtocol.provisionNode( - _getGuardianSignatures(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT + _getGuardianProofs(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT ); vm.deal(NoRestakingModule, 200 ether); @@ -1622,7 +1624,7 @@ contract PufferProtocolTest is UnitTestHelper { uint256 startTimestamp = 1707411226; vm.warp(startTimestamp); pufferProtocol.provisionNode( - _getGuardianSignatures(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT + _getGuardianProofs(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT ); vm.deal(NoRestakingModule, 200 ether); @@ -1674,7 +1676,7 @@ contract PufferProtocolTest is UnitTestHelper { uint256 startTimestamp = 1707411226; vm.warp(startTimestamp); pufferProtocol.provisionNode( - _getGuardianSignatures(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT + _getGuardianProofs(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT ); vm.deal(NoRestakingModule, 200 ether); @@ -1717,7 +1719,7 @@ contract PufferProtocolTest is UnitTestHelper { vm.stopPrank(); pufferProtocol.provisionNode( - _getGuardianSignatures(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT + _getGuardianProofs(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT ); // Alice exited after 1 day @@ -1747,7 +1749,7 @@ contract PufferProtocolTest is UnitTestHelper { vm.stopPrank(); pufferProtocol.provisionNode( - _getGuardianSignatures(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT + _getGuardianProofs(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT ); vm.startPrank(DAO); @@ -1843,12 +1845,12 @@ contract PufferProtocolTest is UnitTestHelper { assertEq(validatorTicket.balanceOf(bob), 50 ether, "bob got the VT"); } - function _getGuardianSignatures(bytes memory pubKey) internal view returns (bytes[] memory) { + function _getGuardianProofs(bytes memory pubKey) internal view returns (GuardianSessionProof[] memory) { (bytes32 moduleName, uint256 pendingIdx) = pufferProtocol.getNextValidatorToProvision(); Validator memory validator = pufferProtocol.getValidatorInfo(moduleName, pendingIdx); // If there is no module return empty byte array if (validator.module == address(0)) { - return new bytes[](0); + return new GuardianSessionProof[](0); } bytes memory withdrawalCredentials = pufferProtocol.getWithdrawalCredentials(validator.module); @@ -1874,12 +1876,32 @@ contract PufferProtocolTest is UnitTestHelper { (v, r, s) = vm.sign(guardian3SKEnclave, digest); bytes memory signature3 = abi.encodePacked(r, s, v); // note the order here is different from line above. - bytes[] memory guardianSignatures = new bytes[](3); - guardianSignatures[0] = signature1; - guardianSignatures[1] = signature2; - guardianSignatures[2] = signature3; + // Pre-computed public keys from makeAddrAndKey() + bytes memory guardian1OwnerPubkey = hex"04af497e622b580acc7e8d961bc7fa69aad88774ea39c838ff5411ac87746eb0d0b157c9e9b6f94d4b58313c7c59c975760b4c640e78d9e466e1a2255359d6e092"; + bytes memory guardian2OwnerPubkey = hex"04169f04b8a0f6c552666fbccf9a73184bb0e2a1fbeb66ee56ca2c3271f9398803cad67262f0987f9ea085771868683b53944d421a081a73cce357275b47f3629f"; + bytes memory guardian3OwnerPubkey = hex"04bcb747c6ce73688d800755ac8715198ca92e7d2f0a828e083e254078c8c652e64f15534685ba90ec89362c8c276df81c7e6a2db9f2f2620d7596d9962171d2fc"; + + GuardianSessionProof[] memory guardianProofs = new GuardianSessionProof[](3); + guardianProofs[0] = GuardianSessionProof({ + sessionId: keccak256("guardian1"), + sessionKey: PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian1EnclavePubKey }), + ownerKey: PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian1OwnerPubkey }), + signature: signature1 + }); + guardianProofs[1] = GuardianSessionProof({ + sessionId: keccak256("guardian2"), + sessionKey: PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian2EnclavePubKey }), + ownerKey: PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian2OwnerPubkey }), + signature: signature2 + }); + guardianProofs[2] = GuardianSessionProof({ + sessionId: keccak256("guardian3"), + sessionKey: PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian3EnclavePubKey }), + ownerKey: PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian3OwnerPubkey }), + signature: signature3 + }); - return guardianSignatures; + return guardianProofs; } function _getGuardianSignaturesForSkipping() internal view returns (bytes[] memory) { @@ -2023,7 +2045,7 @@ contract PufferProtocolTest is UnitTestHelper { vm.stopPrank(); pufferProtocol.provisionNode( - _getGuardianSignatures(_getPubKey(pubKeyPart)), _validatorSignature(), DEFAULT_DEPOSIT_ROOT + _getGuardianProofs(_getPubKey(pubKeyPart)), _validatorSignature(), DEFAULT_DEPOSIT_ROOT ); } diff --git a/mainnet-contracts/test/unit/Timelock.t.sol b/mainnet-contracts/test/unit/Timelock.t.sol index ce6fc788..e5a521aa 100644 --- a/mainnet-contracts/test/unit/Timelock.t.sol +++ b/mainnet-contracts/test/unit/Timelock.t.sol @@ -18,6 +18,8 @@ contract TimelockTest is Test { stETHMock public stETH; Timelock public timelock; + address public constant BROADCASTER = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266; + function setUp() public { PufferDeployment memory deployment = new DeployPufETH().run(); @@ -33,6 +35,7 @@ contract TimelockTest is Test { vm.assume(caller != timelock.OPERATIONS_MULTISIG()); vm.assume(caller != address(timelock)); vm.assume(caller != address(accessManager)); + vm.assume(caller != BROADCASTER); // Upgrades are forbidden (bool canCall, uint32 delay) = @@ -236,10 +239,11 @@ contract TimelockTest is Test { assertTrue(!canCall, "should not be able to call"); } - function test_pause_depositor_slectors(address caller) public { + function test_pause_depositor_selectors(address caller) public { vm.startPrank(timelock.pauserMultisig()); vm.assume(caller != address(timelock)); vm.assume(caller != address(accessManager)); + vm.assume(caller != BROADCASTER); address[] memory targets = new address[](1); targets[0] = address(pufferDepositor); @@ -308,4 +312,4 @@ contract TimelockTest is Test { } } } -} +} \ No newline at end of file From f869e7de09f45d2b4097d599b2d445b608eca7cf Mon Sep 17 00:00:00 2001 From: Eladio Date: Fri, 13 Feb 2026 18:50:32 +0100 Subject: [PATCH 23/51] fmt --- .../script/DeployEverything.s.sol | 3 +- .../script/DeployGuardians.s.sol | 3 +- mainnet-contracts/src/GuardianModule.sol | 139 +++++++----------- mainnet-contracts/src/PufferProtocol.sol | 6 +- .../src/interface/IGuardianModule.sol | 8 +- .../test/handlers/PufferProtocolHandler.sol | 20 ++- .../test/helpers/IntegrationTestHelper.sol | 3 +- .../test/helpers/UnitTestHelper.sol | 4 +- .../test/mocks/SessionRegistryMock.sol | 18 +-- .../test/unit/PufferProtocol.t.sol | 9 +- mainnet-contracts/test/unit/Timelock.t.sol | 2 +- 11 files changed, 95 insertions(+), 120 deletions(-) diff --git a/mainnet-contracts/script/DeployEverything.s.sol b/mainnet-contracts/script/DeployEverything.s.sol index ea847a18..b34030e4 100644 --- a/mainnet-contracts/script/DeployEverything.s.sol +++ b/mainnet-contracts/script/DeployEverything.s.sol @@ -16,7 +16,8 @@ import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy import { GenerateRevenueDepositorCalldata } from "script/AccessManagerMigrations/06_GenerateRevenueDepositorCalldata.s.sol"; import { MockAeraVault } from "test/mocks/MockAeraVault.sol"; -import { ISessionRegistry } from "@automata-network/automata-tee-workload-measurement/interfaces/registries/ISessionRegistry.sol"; +import { ISessionRegistry } from + "@automata-network/automata-tee-workload-measurement/interfaces/registries/ISessionRegistry.sol"; /** * @title Deploy all protocol contracts diff --git a/mainnet-contracts/script/DeployGuardians.s.sol b/mainnet-contracts/script/DeployGuardians.s.sol index b1a5cf9a..bb45ca6c 100644 --- a/mainnet-contracts/script/DeployGuardians.s.sol +++ b/mainnet-contracts/script/DeployGuardians.s.sol @@ -5,7 +5,8 @@ import { BaseScript } from "script/BaseScript.s.sol"; import { GuardianModule } from "../src/GuardianModule.sol"; import { AccessManager } from "@openzeppelin/contracts/access/manager/AccessManager.sol"; import { GuardiansDeployment } from "./DeploymentStructs.sol"; -import { ISessionRegistry } from "@automata-network/automata-tee-workload-measurement/interfaces/registries/ISessionRegistry.sol"; +import { ISessionRegistry } from + "@automata-network/automata-tee-workload-measurement/interfaces/registries/ISessionRegistry.sol"; // forge script script/1_DeployGuardians.s.sol:DeployGuardians --rpc-url=$EPHEMERY_RPC_URL --sig 'run(address, address, address[] calldata, uint256)' "[0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0]" 1 contract DeployGuardians is BaseScript { diff --git a/mainnet-contracts/src/GuardianModule.sol b/mainnet-contracts/src/GuardianModule.sol index e6c7ede5..c8cff8bd 100644 --- a/mainnet-contracts/src/GuardianModule.sol +++ b/mainnet-contracts/src/GuardianModule.sol @@ -10,7 +10,11 @@ import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableS import { LibGuardianMessages } from "./LibGuardianMessages.sol"; import { Address } from "@openzeppelin/contracts/utils/Address.sol"; import { StoppedValidatorInfo } from "./struct/StoppedValidatorInfo.sol"; -import { ISessionRegistry, PublicIdentity, CVMSession } from "@automata-network/automata-tee-workload-measurement/interfaces/registries/ISessionRegistry.sol"; +import { + ISessionRegistry, + PublicIdentity, + CVMSession +} from "@automata-network/automata-tee-workload-measurement/interfaces/registries/ISessionRegistry.sol"; import { LibKey } from "@automata-network/automata-tee-workload-measurement/lib/LibKey.sol"; import { ALGO_ID_ES256K } from "@automata-network/automata-tee-workload-measurement/types/Constants.sol"; @@ -82,7 +86,7 @@ contract GuardianModule is AccessManaged, IGuardianModule { _setThreshold(threshold); } - receive() external payable {} + receive() external payable { } /* * @notice Splits the funds among the guardians @@ -106,19 +110,15 @@ contract GuardianModule is AccessManaged, IGuardianModule { /** * @inheritdoc IGuardianModule */ - function validateSkipProvisioning( - bytes32 moduleName, - uint256 skippedIndex, - bytes[] calldata eoaSignatures - ) external view { - bytes32 signedMessageHash = LibGuardianMessages - ._getSkipProvisioningMessage(moduleName, skippedIndex); + function validateSkipProvisioning(bytes32 moduleName, uint256 skippedIndex, bytes[] calldata eoaSignatures) + external + view + { + bytes32 signedMessageHash = LibGuardianMessages._getSkipProvisioningMessage(moduleName, skippedIndex); // Check the signatures - bool validSignatures = validateGuardiansEOASignatures({ - eoaSignatures: eoaSignatures, - signedMessageHash: signedMessageHash - }); + bool validSignatures = + validateGuardiansEOASignatures({ eoaSignatures: eoaSignatures, signedMessageHash: signedMessageHash }); if (!validSignatures) { revert Unauthorized(); @@ -137,19 +137,15 @@ contract GuardianModule is AccessManaged, IGuardianModule { GuardianSessionProof[] calldata guardianProofs ) external view { // Recreate the message hash - bytes32 signedMessageHash = LibGuardianMessages - ._getBeaconDepositMessageToBeSigned({ - pufferModuleIndex: pufferModuleIndex, - pubKey: pubKey, - signature: signature, - withdrawalCredentials: withdrawalCredentials, - depositDataRoot: depositDataRoot - }); - - bool validSessionProofs = validateSessionProofs( - guardianProofs, - signedMessageHash - ); + bytes32 signedMessageHash = LibGuardianMessages._getBeaconDepositMessageToBeSigned({ + pufferModuleIndex: pufferModuleIndex, + pubKey: pubKey, + signature: signature, + withdrawalCredentials: withdrawalCredentials, + depositDataRoot: depositDataRoot + }); + + bool validSessionProofs = validateSessionProofs(guardianProofs, signedMessageHash); if (!validSessionProofs) { revert Unauthorized(); } @@ -158,18 +154,15 @@ contract GuardianModule is AccessManaged, IGuardianModule { /** * @inheritdoc IGuardianModule */ - function validateBatchWithdrawals( - StoppedValidatorInfo[] calldata validatorInfos, - bytes[] calldata eoaSignatures - ) external view { - bytes32 signedMessageHash = LibGuardianMessages - ._getHandleBatchWithdrawalMessage(validatorInfos); + function validateBatchWithdrawals(StoppedValidatorInfo[] calldata validatorInfos, bytes[] calldata eoaSignatures) + external + view + { + bytes32 signedMessageHash = LibGuardianMessages._getHandleBatchWithdrawalMessage(validatorInfos); // Check the signatures - bool validSignatures = validateGuardiansEOASignatures({ - eoaSignatures: eoaSignatures, - signedMessageHash: signedMessageHash - }); + bool validSignatures = + validateGuardiansEOASignatures({ eoaSignatures: eoaSignatures, signedMessageHash: signedMessageHash }); if (!validSignatures) { revert Unauthorized(); @@ -185,17 +178,12 @@ contract GuardianModule is AccessManaged, IGuardianModule { bytes[] calldata eoaSignatures ) external view { // Recreate the message hash - bytes32 signedMessageHash = LibGuardianMessages - ._getSetNumberOfValidatorsMessage( - newNumberOfValidators, - epochNumber - ); + bytes32 signedMessageHash = + LibGuardianMessages._getSetNumberOfValidatorsMessage(newNumberOfValidators, epochNumber); // Check the signatures - bool validSignatures = validateGuardiansEOASignatures({ - eoaSignatures: eoaSignatures, - signedMessageHash: signedMessageHash - }); + bool validSignatures = + validateGuardiansEOASignatures({ eoaSignatures: eoaSignatures, signedMessageHash: signedMessageHash }); if (!validSignatures) { revert Unauthorized(); @@ -205,25 +193,22 @@ contract GuardianModule is AccessManaged, IGuardianModule { /** * @inheritdoc IGuardianModule */ - function validateGuardiansEOASignatures( - bytes[] calldata eoaSignatures, - bytes32 signedMessageHash - ) public view returns (bool) { - return - _validateSignatures( - _guardians.values(), - eoaSignatures, - signedMessageHash - ); + function validateGuardiansEOASignatures(bytes[] calldata eoaSignatures, bytes32 signedMessageHash) + public + view + returns (bool) + { + return _validateSignatures(_guardians.values(), eoaSignatures, signedMessageHash); } /** * @inheritdoc IGuardianModule */ - function validateSessionProofs( - GuardianSessionProof[] calldata guardianProofs, - bytes32 signedMessageHash - ) public view returns (bool) { + function validateSessionProofs(GuardianSessionProof[] calldata guardianProofs, bytes32 signedMessageHash) + public + view + returns (bool) + { uint256 threshold = _threshold; uint256 proofsLen = guardianProofs.length; require(proofsLen >= threshold, Unauthorized()); @@ -278,19 +263,11 @@ contract GuardianModule is AccessManaged, IGuardianModule { guardian = address(uint160(uint256(keccak256(ownerKey.key[1:])))); require(_guardians.contains(guardian), Unauthorized()); - bool valid = SESSION_REGISTRY.verifySessionSignature( - sessionId, - sessionKey, - signedMessageHash, - signature - ); + bool valid = SESSION_REGISTRY.verifySessionSignature(sessionId, sessionKey, signedMessageHash, signature); require(valid, InvalidSignature()); bytes32 ownerFingerprint = SESSION_REGISTRY.getSessionOwner(sessionId); - require( - ownerFingerprint == LibKey.computeKeyFingerprint(ownerKey), - InvalidECDSAPubKey() - ); + require(ownerFingerprint == LibKey.computeKeyFingerprint(ownerKey), InvalidECDSAPubKey()); CVMSession memory session = SESSION_REGISTRY.getSession(sessionId); require(_allowedWorkloads[session.workloadId], WorkloadNotAllowed()); @@ -308,10 +285,7 @@ contract GuardianModule is AccessManaged, IGuardianModule { * @inheritdoc IGuardianModule * @dev Restricted to the DAO */ - function setAllowedWorkload( - bytes32 workloadId, - bool allowed - ) external restricted { + function setAllowedWorkload(bytes32 workloadId, bool allowed) external restricted { _allowedWorkloads[workloadId] = allowed; emit WorkloadAllowanceChanged(workloadId, allowed); } @@ -381,9 +355,7 @@ contract GuardianModule is AccessManaged, IGuardianModule { /** * @inheritdoc IGuardianModule */ - function isWorkloadAllowed( - bytes32 workloadId - ) external view returns (bool) { + function isWorkloadAllowed(bytes32 workloadId) external view returns (bool) { return _allowedWorkloads[workloadId]; } @@ -426,17 +398,17 @@ contract GuardianModule is AccessManaged, IGuardianModule { * @param signedMessageHash The hash of the signed message * @return A boolean indicating whether the signatures are valid */ - function _validateSignatures( - address[] memory signers, - bytes[] calldata signatures, - bytes32 signedMessageHash - ) internal view returns (bool) { + function _validateSignatures(address[] memory signers, bytes[] calldata signatures, bytes32 signedMessageHash) + internal + view + returns (bool) + { uint256 validSignatures; // We only count signature as valid if it's from the correct signer for (uint256 i; i < signers.length; ++i) { - (address currentSigner, ECDSA.RecoverError recoverError, ) = ECDSA - .tryRecover(signedMessageHash, signatures[i]); + (address currentSigner, ECDSA.RecoverError recoverError,) = + ECDSA.tryRecover(signedMessageHash, signatures[i]); if (recoverError == ECDSA.RecoverError.NoError) { if (currentSigner == signers[i]) { ++validSignatures; @@ -446,5 +418,4 @@ contract GuardianModule is AccessManaged, IGuardianModule { return validSignatures < _threshold ? false : true; } - } diff --git a/mainnet-contracts/src/PufferProtocol.sol b/mainnet-contracts/src/PufferProtocol.sol index cf3b4080..7779537a 100644 --- a/mainnet-contracts/src/PufferProtocol.sol +++ b/mainnet-contracts/src/PufferProtocol.sol @@ -612,11 +612,7 @@ contract PufferProtocol is IPufferProtocol, AccessManagedUpgradeable, UUPSUpgrad /** * @notice Returns necessary information to make Guardian's life easier */ - function getPayload(bytes32 moduleName, bool usingEnclave) - external - view - returns (bytes memory, uint256, uint256) - { + function getPayload(bytes32 moduleName, bool usingEnclave) external view returns (bytes memory, uint256, uint256) { ProtocolStorage storage $ = _getPufferProtocolStorage(); bytes memory withdrawalCredentials = getWithdrawalCredentials(address($.modules[moduleName])); diff --git a/mainnet-contracts/src/interface/IGuardianModule.sol b/mainnet-contracts/src/interface/IGuardianModule.sol index b359269e..96b7b0ad 100644 --- a/mainnet-contracts/src/interface/IGuardianModule.sol +++ b/mainnet-contracts/src/interface/IGuardianModule.sol @@ -239,10 +239,10 @@ interface IGuardianModule { * @param signedMessageHash The message hash that was signed * @return A boolean indicating whether the session proofs are valid and meet the threshold requirement */ - function validateSessionProofs( - GuardianSessionProof[] calldata guardianProofs, - bytes32 signedMessageHash - )external view returns (bool); + function validateSessionProofs(GuardianSessionProof[] calldata guardianProofs, bytes32 signedMessageHash) + external + view + returns (bool); /** * @notice Checks if an account is a guardian diff --git a/mainnet-contracts/test/handlers/PufferProtocolHandler.sol b/mainnet-contracts/test/handlers/PufferProtocolHandler.sol index 89eb08d6..e85e1899 100644 --- a/mainnet-contracts/test/handlers/PufferProtocolHandler.sol +++ b/mainnet-contracts/test/handlers/PufferProtocolHandler.sol @@ -43,12 +43,15 @@ contract PufferProtocolHandler is Test { // Guardians are preset for the test environment, and these are the enclave secret keys uint256 guardian1SKEnclave = 81165043675487275545095207072241430673874640255053335052777448899322561824201; address guardian1Enclave = vm.addr(guardian1SKEnclave); - bytes guardian1EnclavePubkey = hex"04caf1f9cd82a1284626d405d285250fd6c4f58c469fda05d7fd4f29318aae38e7ccc6f4eaced74d3e2aa3fc0576093860d3045263c4183d694a39911ee9031c73"; + bytes guardian1EnclavePubkey = + hex"04caf1f9cd82a1284626d405d285250fd6c4f58c469fda05d7fd4f29318aae38e7ccc6f4eaced74d3e2aa3fc0576093860d3045263c4183d694a39911ee9031c73"; uint256 guardian2SKEnclave = 90480947395980135991870782913815514305328820213706480966227475230529794843518; address guardian2Enclave = vm.addr(guardian2SKEnclave); - bytes guardian2EnclavePubkey = hex"04f050c3ce5d575600af388f41876e2962499a97bc8fcfa4a12adf7e4a486a3be9a1db0efd899c09723f83fe490e8215fd596a5f03c819e28a8b95f3cce6238613"; + bytes guardian2EnclavePubkey = + hex"04f050c3ce5d575600af388f41876e2962499a97bc8fcfa4a12adf7e4a486a3be9a1db0efd899c09723f83fe490e8215fd596a5f03c819e28a8b95f3cce6238613"; uint256 guardian3SKEnclave = 56094429399408807348734910221877888701411489680816282162734349635927251229227; - bytes guardian3EnclavePubkey = hex"04a55b152177219971a93a64aafc2d61baeaf86526963caa260e71efa2b865527e0307d7bda85312dd6ff23bcc88f2bf228da6295239f72c31b686c48b7b69cdfd"; + bytes guardian3EnclavePubkey = + hex"04a55b152177219971a93a64aafc2d61baeaf86526963caa260e71efa2b865527e0307d7bda85312dd6ff23bcc88f2bf228da6295239f72c31b686c48b7b69cdfd"; UnitTestHelper testhelper; address[] public actors; @@ -634,11 +637,13 @@ contract PufferProtocolHandler is Test { (v, r, s) = vm.sign(guardian3SKEnclave, digest); bytes memory signature3 = abi.encodePacked(r, s, v); // note the order here is different from line above. - // Pre-computed public keys from makeAddrAndKey() - bytes memory guardian1OwnerPubkey = hex"04af497e622b580acc7e8d961bc7fa69aad88774ea39c838ff5411ac87746eb0d0b157c9e9b6f94d4b58313c7c59c975760b4c640e78d9e466e1a2255359d6e092"; - bytes memory guardian2OwnerPubkey = hex"04169f04b8a0f6c552666fbccf9a73184bb0e2a1fbeb66ee56ca2c3271f9398803cad67262f0987f9ea085771868683b53944d421a081a73cce357275b47f3629f"; - bytes memory guardian3OwnerPubkey = hex"04bcb747c6ce73688d800755ac8715198ca92e7d2f0a828e083e254078c8c652e64f15534685ba90ec89362c8c276df81c7e6a2db9f2f2620d7596d9962171d2fc"; + bytes memory guardian1OwnerPubkey = + hex"04af497e622b580acc7e8d961bc7fa69aad88774ea39c838ff5411ac87746eb0d0b157c9e9b6f94d4b58313c7c59c975760b4c640e78d9e466e1a2255359d6e092"; + bytes memory guardian2OwnerPubkey = + hex"04169f04b8a0f6c552666fbccf9a73184bb0e2a1fbeb66ee56ca2c3271f9398803cad67262f0987f9ea085771868683b53944d421a081a73cce357275b47f3629f"; + bytes memory guardian3OwnerPubkey = + hex"04bcb747c6ce73688d800755ac8715198ca92e7d2f0a828e083e254078c8c652e64f15534685ba90ec89362c8c276df81c7e6a2db9f2f2620d7596d9962171d2fc"; GuardianSessionProof[] memory guardianProofs = new GuardianSessionProof[](3); guardianProofs[0] = GuardianSessionProof({ @@ -723,5 +728,4 @@ contract PufferProtocolHandler is Test { AccessManager(pufferProtocol.authority()).setTargetFunctionRole(module, selectors, ROLE_ID_PUFFER_PROTOCOL); vm.stopPrank(); } - } diff --git a/mainnet-contracts/test/helpers/IntegrationTestHelper.sol b/mainnet-contracts/test/helpers/IntegrationTestHelper.sol index 8d6f7541..7df4007b 100644 --- a/mainnet-contracts/test/helpers/IntegrationTestHelper.sol +++ b/mainnet-contracts/test/helpers/IntegrationTestHelper.sol @@ -10,7 +10,8 @@ import { PufferModuleManager } from "../../src/PufferModuleManager.sol"; import { UpgradeableBeacon } from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; import { DeployEverything } from "script/DeployEverything.s.sol"; import { AccessManager } from "@openzeppelin/contracts/access/manager/AccessManager.sol"; -import { ISessionRegistry } from "@automata-network/automata-tee-workload-measurement/interfaces/registries/ISessionRegistry.sol"; +import { ISessionRegistry } from + "@automata-network/automata-tee-workload-measurement/interfaces/registries/ISessionRegistry.sol"; contract IntegrationTestHelper is Test { address DAO = 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; diff --git a/mainnet-contracts/test/helpers/UnitTestHelper.sol b/mainnet-contracts/test/helpers/UnitTestHelper.sol index 8d1dac05..9aa5ccc6 100644 --- a/mainnet-contracts/test/helpers/UnitTestHelper.sol +++ b/mainnet-contracts/test/helpers/UnitTestHelper.sol @@ -22,7 +22,8 @@ import { PufferProtocolDeployment, BridgingDeployment } from "../../script/Deplo // import { TeeReportType } from "@automata-network/automata-tee-workload-measurement/lib/LibTEE.sol"; // import { MeasureablePcr } from "@automata-network/automata-tpm-attestation/interfaces/ITpmAttestation.sol"; // import { GoldenMeasurementInfo, TdxRegistrationData } from "../../src/struct/GuardianModuleStructs.sol"; -import { ISessionRegistry } from "@automata-network/automata-tee-workload-measurement/interfaces/registries/ISessionRegistry.sol"; +import { ISessionRegistry } from + "@automata-network/automata-tee-workload-measurement/interfaces/registries/ISessionRegistry.sol"; import { AccessManager } from "@openzeppelin/contracts/access/manager/AccessManager.sol"; import { Permit } from "../../src/structs/Permit.sol"; import { PufferDepositor } from "../../src/PufferDepositor.sol"; @@ -340,5 +341,4 @@ contract UnitTestHelper is Test, BaseScript { t.amount = amount; t.deadline = deadline; } - } diff --git a/mainnet-contracts/test/mocks/SessionRegistryMock.sol b/mainnet-contracts/test/mocks/SessionRegistryMock.sol index 2c56f5f4..cd0e0cf7 100644 --- a/mainnet-contracts/test/mocks/SessionRegistryMock.sol +++ b/mainnet-contracts/test/mocks/SessionRegistryMock.sol @@ -1,18 +1,16 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.0 <0.9.0; -import {CVMSession, PublicIdentity} from "@automata-network/automata-tee-workload-measurement/interfaces/registries/ISessionRegistry.sol"; -import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import { + CVMSession, + PublicIdentity +} from "@automata-network/automata-tee-workload-measurement/interfaces/registries/ISessionRegistry.sol"; +import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; contract SessionRegistryMock { + function getSession(bytes32 sessionId) external view returns (CVMSession memory session) { } - function getSession(bytes32 sessionId) external view returns (CVMSession memory session) { - - } - - function getSessionOwner(bytes32 sessionId) external view returns (bytes32 ownerFingerprint) { - - } + function getSessionOwner(bytes32 sessionId) external view returns (bytes32 ownerFingerprint) { } function verifySessionSignature( bytes32 sessionId, @@ -43,4 +41,4 @@ contract SessionRegistryMock { // Valid only if recovery succeeded and address matches return err == ECDSA.RecoverError.NoError && recovered == expectedAddress; } -} \ No newline at end of file +} diff --git a/mainnet-contracts/test/unit/PufferProtocol.t.sol b/mainnet-contracts/test/unit/PufferProtocol.t.sol index 534f3e65..f00d878a 100644 --- a/mainnet-contracts/test/unit/PufferProtocol.t.sol +++ b/mainnet-contracts/test/unit/PufferProtocol.t.sol @@ -1877,9 +1877,12 @@ contract PufferProtocolTest is UnitTestHelper { bytes memory signature3 = abi.encodePacked(r, s, v); // note the order here is different from line above. // Pre-computed public keys from makeAddrAndKey() - bytes memory guardian1OwnerPubkey = hex"04af497e622b580acc7e8d961bc7fa69aad88774ea39c838ff5411ac87746eb0d0b157c9e9b6f94d4b58313c7c59c975760b4c640e78d9e466e1a2255359d6e092"; - bytes memory guardian2OwnerPubkey = hex"04169f04b8a0f6c552666fbccf9a73184bb0e2a1fbeb66ee56ca2c3271f9398803cad67262f0987f9ea085771868683b53944d421a081a73cce357275b47f3629f"; - bytes memory guardian3OwnerPubkey = hex"04bcb747c6ce73688d800755ac8715198ca92e7d2f0a828e083e254078c8c652e64f15534685ba90ec89362c8c276df81c7e6a2db9f2f2620d7596d9962171d2fc"; + bytes memory guardian1OwnerPubkey = + hex"04af497e622b580acc7e8d961bc7fa69aad88774ea39c838ff5411ac87746eb0d0b157c9e9b6f94d4b58313c7c59c975760b4c640e78d9e466e1a2255359d6e092"; + bytes memory guardian2OwnerPubkey = + hex"04169f04b8a0f6c552666fbccf9a73184bb0e2a1fbeb66ee56ca2c3271f9398803cad67262f0987f9ea085771868683b53944d421a081a73cce357275b47f3629f"; + bytes memory guardian3OwnerPubkey = + hex"04bcb747c6ce73688d800755ac8715198ca92e7d2f0a828e083e254078c8c652e64f15534685ba90ec89362c8c276df81c7e6a2db9f2f2620d7596d9962171d2fc"; GuardianSessionProof[] memory guardianProofs = new GuardianSessionProof[](3); guardianProofs[0] = GuardianSessionProof({ diff --git a/mainnet-contracts/test/unit/Timelock.t.sol b/mainnet-contracts/test/unit/Timelock.t.sol index e5a521aa..a7bab6c7 100644 --- a/mainnet-contracts/test/unit/Timelock.t.sol +++ b/mainnet-contracts/test/unit/Timelock.t.sol @@ -312,4 +312,4 @@ contract TimelockTest is Test { } } } -} \ No newline at end of file +} From 02a42fbebd061d6a8a45fa511e191e18be0ab0a4 Mon Sep 17 00:00:00 2001 From: Eladio Date: Mon, 16 Feb 2026 13:07:42 +0100 Subject: [PATCH 24/51] Fixed tests --- .../test/helpers/UnitTestHelper.sol | 43 ++++++++++++++++- .../test/mocks/SessionRegistryMock.sol | 34 ++++++++++++-- mainnet-contracts/test/unit/PUFER.t.sol | 2 + .../test/unit/PufferProtocol.t.sol | 46 ++++++++++--------- 4 files changed, 97 insertions(+), 28 deletions(-) diff --git a/mainnet-contracts/test/helpers/UnitTestHelper.sol b/mainnet-contracts/test/helpers/UnitTestHelper.sol index 9aa5ccc6..bcc93e68 100644 --- a/mainnet-contracts/test/helpers/UnitTestHelper.sol +++ b/mainnet-contracts/test/helpers/UnitTestHelper.sol @@ -9,7 +9,7 @@ import { PufferProtocol } from "../../src/PufferProtocol.sol"; import { PufferModuleManager } from "../../src/PufferModuleManager.sol"; import { AVSContractsRegistry } from "../../src/AVSContractsRegistry.sol"; import { RestakingOperatorController } from "../../src/RestakingOperatorController.sol"; -import { IGuardianModule } from "../../src/interface/IGuardianModule.sol"; +import { IGuardianModule, PublicIdentity } from "../../src/interface/IGuardianModule.sol"; import { UpgradeableBeacon } from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; import { DeployEverything } from "../../script/DeployEverything.s.sol"; import { PufferProtocolDeployment, BridgingDeployment } from "../../script/DeploymentStructs.sol"; @@ -24,6 +24,8 @@ import { PufferProtocolDeployment, BridgingDeployment } from "../../script/Deplo // import { GoldenMeasurementInfo, TdxRegistrationData } from "../../src/struct/GuardianModuleStructs.sol"; import { ISessionRegistry } from "@automata-network/automata-tee-workload-measurement/interfaces/registries/ISessionRegistry.sol"; +import { ALGO_ID_ES256K } from "@automata-network/automata-tee-workload-measurement/types/Constants.sol"; +import { LibKey } from "@automata-network/automata-tee-workload-measurement/lib/LibKey.sol"; import { AccessManager } from "@openzeppelin/contracts/access/manager/AccessManager.sol"; import { Permit } from "../../src/structs/Permit.sol"; import { PufferDepositor } from "../../src/PufferDepositor.sol"; @@ -93,6 +95,27 @@ contract UnitTestHelper is Test, BaseScript { bytes public guardian3EnclavePubKey = hex"04a55b152177219971a93a64aafc2d61baeaf86526963caa260e71efa2b865527e0307d7bda85312dd6ff23bcc88f2bf228da6295239f72c31b686c48b7b69cdfd"; + bytes public guardian1OwnerPubKey = + hex"04af497e622b580acc7e8d961bc7fa69aad88774ea39c838ff5411ac87746eb0d0b157c9e9b6f94d4b58313c7c59c975760b4c640e78d9e466e1a2255359d6e092"; + bytes public guardian2OwnerPubKey = + hex"04169f04b8a0f6c552666fbccf9a73184bb0e2a1fbeb66ee56ca2c3271f9398803cad67262f0987f9ea085771868683b53944d421a081a73cce357275b47f3629f"; + bytes public guardian3OwnerPubKey = + hex"04bcb747c6ce73688d800755ac8715198ca92e7d2f0a828e083e254078c8c652e64f15534685ba90ec89362c8c276df81c7e6a2db9f2f2620d7596d9962171d2fc"; + + PublicIdentity public guardian1OwnerPublicIdentity; + PublicIdentity public guardian2OwnerPublicIdentity; + PublicIdentity public guardian3OwnerPublicIdentity; + + PublicIdentity public guardian1SessionPublicIdentity; + PublicIdentity public guardian2SessionPublicIdentity; + PublicIdentity public guardian3SessionPublicIdentity; + + bytes32 public guardian1SessionId; + bytes32 public guardian2SessionId; + bytes32 public guardian3SessionId; + + SessionRegistryMock public sessionRegistryMock; + // TDX attestation test data bytes public guardian1TdxAttestationReport = hex""; @@ -210,7 +233,7 @@ contract UnitTestHelper is Test, BaseScript { guardians[1] = guardian2; guardians[2] = guardian3; - SessionRegistryMock sessionRegistryMock = new SessionRegistryMock(); + sessionRegistryMock = new SessionRegistryMock(); // Deploy everything with one script PufferProtocolDeployment memory pufferDeployment; @@ -257,6 +280,21 @@ contract UnitTestHelper is Test, BaseScript { // No longer enclave adrresses in GuardianModule // TODO Check if need to config session registry mock + guardian1OwnerPublicIdentity = PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian1OwnerPubKey }); + guardian2OwnerPublicIdentity = PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian2OwnerPubKey }); + guardian3OwnerPublicIdentity = PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian3OwnerPubKey }); + + guardian1SessionPublicIdentity = PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian1EnclavePubKey }); + guardian2SessionPublicIdentity = PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian2EnclavePubKey }); + guardian3SessionPublicIdentity = PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian3EnclavePubKey }); + + guardian1SessionId = keccak256("guardian1"); + guardian2SessionId = keccak256("guardian2"); + guardian3SessionId = keccak256("guardian3"); + + sessionRegistryMock.setSessionOwner(guardian1SessionId, LibKey.computeKeyFingerprint(guardian1OwnerPublicIdentity)); + sessionRegistryMock.setSessionOwner(guardian2SessionId, LibKey.computeKeyFingerprint(guardian2OwnerPublicIdentity)); + sessionRegistryMock.setSessionOwner(guardian3SessionId, LibKey.computeKeyFingerprint(guardian3OwnerPublicIdentity)); } function _upgradePufferVaultToMainnet() internal { @@ -341,4 +379,5 @@ contract UnitTestHelper is Test, BaseScript { t.amount = amount; t.deadline = deadline; } + } diff --git a/mainnet-contracts/test/mocks/SessionRegistryMock.sol b/mainnet-contracts/test/mocks/SessionRegistryMock.sol index cd0e0cf7..002e801b 100644 --- a/mainnet-contracts/test/mocks/SessionRegistryMock.sol +++ b/mainnet-contracts/test/mocks/SessionRegistryMock.sol @@ -8,16 +8,34 @@ import { import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; contract SessionRegistryMock { - function getSession(bytes32 sessionId) external view returns (CVMSession memory session) { } - function getSessionOwner(bytes32 sessionId) external view returns (bytes32 ownerFingerprint) { } + mapping(bytes32 sessionId => bytes32 ownerFingerPrint) private _sessionOwners; + mapping(bytes32 sessionId => bytes32 workload) private _sessionWorkloads; + + function getSession(bytes32 sessionId) external view returns (CVMSession memory session) { + return CVMSession({ + akPubKeyFingerprint: _sessionOwners[sessionId], // Attestation Key (root of trust) + tpmSigningKeyFingerprint: bytes32(0), // TPM Signing Key (extracted from quote) + sessionKeyFingerprint: bytes32(0), // Session Key (operational key) + baseImageId: bytes32(0), // Associated platform image + workloadId: _sessionWorkloads[sessionId], // Associated workload + platformProfileId: bytes32(0), // Platform profile identifier + measurementVariantId: bytes32(0), // Measurement variant identifier + registeredAt: 0, // Registration timestamp + expiresAt: 0 // Expiration timestamp + }); + } + + function getSessionOwner(bytes32 sessionId) external view returns (bytes32 ownerFingerprint) { + return _sessionOwners[sessionId]; + } function verifySessionSignature( - bytes32 sessionId, + bytes32, // sessionId PublicIdentity calldata sessionKey, bytes32 message, bytes calldata signature - ) external view returns (bool valid) { + ) external pure returns (bool valid) { return _verifySecp256k1(sessionKey.key, message, signature); } @@ -41,4 +59,12 @@ contract SessionRegistryMock { // Valid only if recovery succeeded and address matches return err == ECDSA.RecoverError.NoError && recovered == expectedAddress; } + + function setSessionOwner(bytes32 sessionId, bytes32 ownerFingerprint) external { + _sessionOwners[sessionId] = ownerFingerprint; + } + + function setSessionWorkload(bytes32 sessionId, bytes32 workload) external { + _sessionWorkloads[sessionId] = workload; + } } diff --git a/mainnet-contracts/test/unit/PUFER.t.sol b/mainnet-contracts/test/unit/PUFER.t.sol index 10a09987..def4a861 100644 --- a/mainnet-contracts/test/unit/PUFER.t.sol +++ b/mainnet-contracts/test/unit/PUFER.t.sol @@ -31,6 +31,8 @@ contract PUFFERTest is UnitTestHelper { function test_allowedSenderCanTransferToAnybody(address recipient) public { vm.assume(recipient != address(0)); + vm.assume(recipient != alice); + vm.assume(recipient != owner); assertEq(puffer.paused(), true, "PUFFER should be paused"); vm.startPrank(owner); diff --git a/mainnet-contracts/test/unit/PufferProtocol.t.sol b/mainnet-contracts/test/unit/PufferProtocol.t.sol index f00d878a..a21bc96f 100644 --- a/mainnet-contracts/test/unit/PufferProtocol.t.sol +++ b/mainnet-contracts/test/unit/PufferProtocol.t.sol @@ -16,7 +16,7 @@ import { LibGuardianMessages } from "../../src/LibGuardianMessages.sol"; import { Permit } from "../../src/structs/Permit.sol"; import { ModuleLimit } from "../../src/struct/ProtocolStorage.sol"; import { StoppedValidatorInfo } from "../../src/struct/StoppedValidatorInfo.sol"; -import { GuardianSessionProof, PublicIdentity } from "../../src/interface/IGuardianModule.sol"; +import { GuardianSessionProof, PublicIdentity, IGuardianModule } from "../../src/interface/IGuardianModule.sol"; import { ALGO_ID_ES256K } from "@automata-network/automata-tee-workload-measurement/types/Constants.sol"; contract PufferProtocolTest is UnitTestHelper { @@ -76,6 +76,18 @@ contract PufferProtocolTest is UnitTestHelper { NoRestakingModule = pufferProtocol.getModuleAddress(PUFFER_MODULE_0); // Fund no restaking module with 200 ETH vm.deal(NoRestakingModule, 200 ether); + + // TODO Set allowed workload in GuardianModule and sessionRegistry mock + bytes32 workload1 = keccak256("workload1"); + bytes32 workload2 = keccak256("workload2"); + bytes32 workload3 = keccak256("workload3"); + guardianModule.setAllowedWorkload(workload1, true); + guardianModule.setAllowedWorkload(workload2, true); + guardianModule.setAllowedWorkload(workload3, true); + sessionRegistryMock.setSessionWorkload(guardian1SessionId, workload1); + sessionRegistryMock.setSessionWorkload(guardian2SessionId, workload2); + sessionRegistryMock.setSessionWorkload(guardian3SessionId, workload3); + } // Setup @@ -456,7 +468,7 @@ contract PufferProtocolTest is UnitTestHelper { // Provisioning of rocky should fail, because jason is next in line guardianProofs = _getGuardianProofs(_getPubKey(bytes32("rocky"))); - vm.expectRevert(Unauthorized.selector); + vm.expectRevert(IGuardianModule.InvalidSignature.selector); pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); guardianProofs = _getGuardianProofs(_getPubKey(bytes32("jason"))); @@ -756,7 +768,7 @@ contract PufferProtocolTest is UnitTestHelper { // Try to provision it with the original message (replay attack) // It should revert - vm.expectRevert(Unauthorized.selector); + vm.expectRevert(IGuardianModule.InvalidSignature.selector); pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); } @@ -1870,40 +1882,30 @@ contract PufferProtocolTest is UnitTestHelper { bytes memory signature1 = abi.encodePacked(r, s, v); // note the order here is different from line above. (v, r, s) = vm.sign(guardian2SKEnclave, digest); - (v, r, s) = vm.sign(guardian3SKEnclave, digest); bytes memory signature2 = abi.encodePacked(r, s, v); // note the order here is different from line above. (v, r, s) = vm.sign(guardian3SKEnclave, digest); bytes memory signature3 = abi.encodePacked(r, s, v); // note the order here is different from line above. - // Pre-computed public keys from makeAddrAndKey() - bytes memory guardian1OwnerPubkey = - hex"04af497e622b580acc7e8d961bc7fa69aad88774ea39c838ff5411ac87746eb0d0b157c9e9b6f94d4b58313c7c59c975760b4c640e78d9e466e1a2255359d6e092"; - bytes memory guardian2OwnerPubkey = - hex"04169f04b8a0f6c552666fbccf9a73184bb0e2a1fbeb66ee56ca2c3271f9398803cad67262f0987f9ea085771868683b53944d421a081a73cce357275b47f3629f"; - bytes memory guardian3OwnerPubkey = - hex"04bcb747c6ce73688d800755ac8715198ca92e7d2f0a828e083e254078c8c652e64f15534685ba90ec89362c8c276df81c7e6a2db9f2f2620d7596d9962171d2fc"; - GuardianSessionProof[] memory guardianProofs = new GuardianSessionProof[](3); guardianProofs[0] = GuardianSessionProof({ - sessionId: keccak256("guardian1"), - sessionKey: PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian1EnclavePubKey }), - ownerKey: PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian1OwnerPubkey }), + sessionId: guardian1SessionId, + sessionKey: guardian1SessionPublicIdentity, + ownerKey: guardian1OwnerPublicIdentity, signature: signature1 }); guardianProofs[1] = GuardianSessionProof({ - sessionId: keccak256("guardian2"), - sessionKey: PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian2EnclavePubKey }), - ownerKey: PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian2OwnerPubkey }), + sessionId: guardian2SessionId, + sessionKey: guardian2SessionPublicIdentity, + ownerKey: guardian2OwnerPublicIdentity, signature: signature2 }); guardianProofs[2] = GuardianSessionProof({ - sessionId: keccak256("guardian3"), - sessionKey: PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian3EnclavePubKey }), - ownerKey: PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian3OwnerPubkey }), + sessionId: guardian3SessionId, + sessionKey: guardian3SessionPublicIdentity, + ownerKey: guardian3OwnerPublicIdentity, signature: signature3 }); - return guardianProofs; } From b6496f1fb3288c96973a91e7afa86cecdf57bda6 Mon Sep 17 00:00:00 2001 From: Eladio Date: Mon, 16 Feb 2026 13:54:42 +0100 Subject: [PATCH 25/51] Added extra tests --- .../test/helpers/UnitTestHelper.sol | 1 - .../test/unit/GuardianModule.t.sol | 27 +++++++++ .../test/unit/PufferProtocol.t.sol | 59 +++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/mainnet-contracts/test/helpers/UnitTestHelper.sol b/mainnet-contracts/test/helpers/UnitTestHelper.sol index bcc93e68..f9283592 100644 --- a/mainnet-contracts/test/helpers/UnitTestHelper.sol +++ b/mainnet-contracts/test/helpers/UnitTestHelper.sol @@ -279,7 +279,6 @@ contract UnitTestHelper is Test, BaseScript { vm.label(address(pufferProtocol), "PufferProtocol"); // No longer enclave adrresses in GuardianModule - // TODO Check if need to config session registry mock guardian1OwnerPublicIdentity = PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian1OwnerPubKey }); guardian2OwnerPublicIdentity = PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian2OwnerPubKey }); guardian3OwnerPublicIdentity = PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian3OwnerPubKey }); diff --git a/mainnet-contracts/test/unit/GuardianModule.t.sol b/mainnet-contracts/test/unit/GuardianModule.t.sol index 83ba256d..fc75dc32 100644 --- a/mainnet-contracts/test/unit/GuardianModule.t.sol +++ b/mainnet-contracts/test/unit/GuardianModule.t.sol @@ -119,4 +119,31 @@ contract GuardianModuleTest is UnitTestHelper { assertEq(guardian3.balance, 10); assertEq(address(guardianModule).balance, 2); } + + function test_setAllowedWorkload() public { + vm.startPrank(DAO); + + bytes32 workloadId = keccak256("test_workload"); + + // Initially workload should not be allowed + assertFalse(guardianModule.isWorkloadAllowed(workloadId), "workload should not be allowed initially"); + + // Set workload as allowed + vm.expectEmit(true, true, true, true); + emit IGuardianModule.WorkloadAllowanceChanged(workloadId, true); + guardianModule.setAllowedWorkload(workloadId, true); + + // Verify workload is now allowed + assertTrue(guardianModule.isWorkloadAllowed(workloadId), "workload should be allowed"); + + // Set workload as not allowed + vm.expectEmit(true, true, true, true); + emit IGuardianModule.WorkloadAllowanceChanged(workloadId, false); + guardianModule.setAllowedWorkload(workloadId, false); + + // Verify workload is not allowed anymore + assertFalse(guardianModule.isWorkloadAllowed(workloadId), "workload should not be allowed"); + + vm.stopPrank(); + } } diff --git a/mainnet-contracts/test/unit/PufferProtocol.t.sol b/mainnet-contracts/test/unit/PufferProtocol.t.sol index a21bc96f..001c8b72 100644 --- a/mainnet-contracts/test/unit/PufferProtocol.t.sol +++ b/mainnet-contracts/test/unit/PufferProtocol.t.sol @@ -1857,6 +1857,65 @@ contract PufferProtocolTest is UnitTestHelper { assertEq(validatorTicket.balanceOf(bob), 50 ether, "bob got the VT"); } + function test_failing_verification() public { + + vm.deal(alice, 10 ether); + + vm.startPrank(alice); + _registerValidatorKey(bytes32("alice"), PUFFER_MODULE_0); + vm.stopPrank(); + + // No workload allowed + guardianModule.setAllowedWorkload(keccak256("workload1"), false); + + GuardianSessionProof[] memory proofs = _getGuardianProofs(_getPubKey(bytes32("alice"))); + bytes memory signature = _validatorSignature(); + + vm.expectRevert(IGuardianModule.WorkloadNotAllowed.selector); + pufferProtocol.provisionNode( + proofs, signature, DEFAULT_DEPOSIT_ROOT + ); + + guardianModule.setAllowedWorkload(keccak256("workload1"), true); + + // Invalid type id + proofs[0].ownerKey.typeId = 0; + + vm.expectRevert(IGuardianModule.InvalidECDSAPubKey.selector); + pufferProtocol.provisionNode( + proofs, signature, DEFAULT_DEPOSIT_ROOT + ); + + proofs[0].ownerKey.typeId = ALGO_ID_ES256K; + + // Invalid key length + bytes memory realOwnerKey = proofs[0].ownerKey.key; + proofs[0].ownerKey.key = hex"04caf1"; + + vm.expectRevert(IGuardianModule.InvalidECDSAPubKey.selector); + pufferProtocol.provisionNode( + proofs, signature, DEFAULT_DEPOSIT_ROOT + ); + + proofs[0].ownerKey.key = realOwnerKey; + + // Invalid ownerFingerprint + sessionRegistryMock.setSessionOwner(guardian1SessionId, bytes32("invalidFingerprint")); + + vm.expectRevert(IGuardianModule.InvalidECDSAPubKey.selector); + pufferProtocol.provisionNode( + proofs, signature, DEFAULT_DEPOSIT_ROOT + ); + + // InvalidSignature + + proofs[0].signature = hex"beef"; + vm.expectRevert(IGuardianModule.InvalidSignature.selector); + pufferProtocol.provisionNode( + proofs, signature, DEFAULT_DEPOSIT_ROOT + ); + } + function _getGuardianProofs(bytes memory pubKey) internal view returns (GuardianSessionProof[] memory) { (bytes32 moduleName, uint256 pendingIdx) = pufferProtocol.getNextValidatorToProvision(); Validator memory validator = pufferProtocol.getValidatorInfo(moduleName, pendingIdx); From 2bcb07dfc424069838b728560b580ff9ac1a1201 Mon Sep 17 00:00:00 2001 From: eladiosch <3090613+eladiosch@users.noreply.github.com> Date: Mon, 16 Feb 2026 12:58:44 +0000 Subject: [PATCH 26/51] forge fmt --- .../test/helpers/UnitTestHelper.sol | 13 +++++++---- .../test/mocks/SessionRegistryMock.sol | 5 ++--- .../test/unit/PufferProtocol.t.sol | 22 +++++-------------- 3 files changed, 16 insertions(+), 24 deletions(-) diff --git a/mainnet-contracts/test/helpers/UnitTestHelper.sol b/mainnet-contracts/test/helpers/UnitTestHelper.sol index f9283592..7532a055 100644 --- a/mainnet-contracts/test/helpers/UnitTestHelper.sol +++ b/mainnet-contracts/test/helpers/UnitTestHelper.sol @@ -291,9 +291,15 @@ contract UnitTestHelper is Test, BaseScript { guardian2SessionId = keccak256("guardian2"); guardian3SessionId = keccak256("guardian3"); - sessionRegistryMock.setSessionOwner(guardian1SessionId, LibKey.computeKeyFingerprint(guardian1OwnerPublicIdentity)); - sessionRegistryMock.setSessionOwner(guardian2SessionId, LibKey.computeKeyFingerprint(guardian2OwnerPublicIdentity)); - sessionRegistryMock.setSessionOwner(guardian3SessionId, LibKey.computeKeyFingerprint(guardian3OwnerPublicIdentity)); + sessionRegistryMock.setSessionOwner( + guardian1SessionId, LibKey.computeKeyFingerprint(guardian1OwnerPublicIdentity) + ); + sessionRegistryMock.setSessionOwner( + guardian2SessionId, LibKey.computeKeyFingerprint(guardian2OwnerPublicIdentity) + ); + sessionRegistryMock.setSessionOwner( + guardian3SessionId, LibKey.computeKeyFingerprint(guardian3OwnerPublicIdentity) + ); } function _upgradePufferVaultToMainnet() internal { @@ -378,5 +384,4 @@ contract UnitTestHelper is Test, BaseScript { t.amount = amount; t.deadline = deadline; } - } diff --git a/mainnet-contracts/test/mocks/SessionRegistryMock.sol b/mainnet-contracts/test/mocks/SessionRegistryMock.sol index 002e801b..4eb9a5c4 100644 --- a/mainnet-contracts/test/mocks/SessionRegistryMock.sol +++ b/mainnet-contracts/test/mocks/SessionRegistryMock.sol @@ -8,7 +8,6 @@ import { import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; contract SessionRegistryMock { - mapping(bytes32 sessionId => bytes32 ownerFingerPrint) private _sessionOwners; mapping(bytes32 sessionId => bytes32 workload) private _sessionWorkloads; @@ -23,12 +22,12 @@ contract SessionRegistryMock { measurementVariantId: bytes32(0), // Measurement variant identifier registeredAt: 0, // Registration timestamp expiresAt: 0 // Expiration timestamp - }); + }); } function getSessionOwner(bytes32 sessionId) external view returns (bytes32 ownerFingerprint) { return _sessionOwners[sessionId]; - } + } function verifySessionSignature( bytes32, // sessionId diff --git a/mainnet-contracts/test/unit/PufferProtocol.t.sol b/mainnet-contracts/test/unit/PufferProtocol.t.sol index 001c8b72..322c16ef 100644 --- a/mainnet-contracts/test/unit/PufferProtocol.t.sol +++ b/mainnet-contracts/test/unit/PufferProtocol.t.sol @@ -87,7 +87,6 @@ contract PufferProtocolTest is UnitTestHelper { sessionRegistryMock.setSessionWorkload(guardian1SessionId, workload1); sessionRegistryMock.setSessionWorkload(guardian2SessionId, workload2); sessionRegistryMock.setSessionWorkload(guardian3SessionId, workload3); - } // Setup @@ -1858,7 +1857,6 @@ contract PufferProtocolTest is UnitTestHelper { } function test_failing_verification() public { - vm.deal(alice, 10 ether); vm.startPrank(alice); @@ -1872,9 +1870,7 @@ contract PufferProtocolTest is UnitTestHelper { bytes memory signature = _validatorSignature(); vm.expectRevert(IGuardianModule.WorkloadNotAllowed.selector); - pufferProtocol.provisionNode( - proofs, signature, DEFAULT_DEPOSIT_ROOT - ); + pufferProtocol.provisionNode(proofs, signature, DEFAULT_DEPOSIT_ROOT); guardianModule.setAllowedWorkload(keccak256("workload1"), true); @@ -1882,9 +1878,7 @@ contract PufferProtocolTest is UnitTestHelper { proofs[0].ownerKey.typeId = 0; vm.expectRevert(IGuardianModule.InvalidECDSAPubKey.selector); - pufferProtocol.provisionNode( - proofs, signature, DEFAULT_DEPOSIT_ROOT - ); + pufferProtocol.provisionNode(proofs, signature, DEFAULT_DEPOSIT_ROOT); proofs[0].ownerKey.typeId = ALGO_ID_ES256K; @@ -1893,9 +1887,7 @@ contract PufferProtocolTest is UnitTestHelper { proofs[0].ownerKey.key = hex"04caf1"; vm.expectRevert(IGuardianModule.InvalidECDSAPubKey.selector); - pufferProtocol.provisionNode( - proofs, signature, DEFAULT_DEPOSIT_ROOT - ); + pufferProtocol.provisionNode(proofs, signature, DEFAULT_DEPOSIT_ROOT); proofs[0].ownerKey.key = realOwnerKey; @@ -1903,17 +1895,13 @@ contract PufferProtocolTest is UnitTestHelper { sessionRegistryMock.setSessionOwner(guardian1SessionId, bytes32("invalidFingerprint")); vm.expectRevert(IGuardianModule.InvalidECDSAPubKey.selector); - pufferProtocol.provisionNode( - proofs, signature, DEFAULT_DEPOSIT_ROOT - ); + pufferProtocol.provisionNode(proofs, signature, DEFAULT_DEPOSIT_ROOT); // InvalidSignature proofs[0].signature = hex"beef"; vm.expectRevert(IGuardianModule.InvalidSignature.selector); - pufferProtocol.provisionNode( - proofs, signature, DEFAULT_DEPOSIT_ROOT - ); + pufferProtocol.provisionNode(proofs, signature, DEFAULT_DEPOSIT_ROOT); } function _getGuardianProofs(bytes memory pubKey) internal view returns (GuardianSessionProof[] memory) { From 96df12b0599fb68523217c290d4273bcc56b9add Mon Sep 17 00:00:00 2001 From: Eladio Date: Tue, 17 Feb 2026 17:48:28 +0100 Subject: [PATCH 27/51] Addressed PR comments --- mainnet-contracts/src/GuardianModule.sol | 7 ++-- .../src/interface/IGuardianModule.sol | 32 ------------------- .../test/unit/GuardianModule.t.sol | 3 ++ 3 files changed, 8 insertions(+), 34 deletions(-) diff --git a/mainnet-contracts/src/GuardianModule.sol b/mainnet-contracts/src/GuardianModule.sol index c8cff8bd..378b7e55 100644 --- a/mainnet-contracts/src/GuardianModule.sol +++ b/mainnet-contracts/src/GuardianModule.sol @@ -21,7 +21,9 @@ import { ALGO_ID_ES256K } from "@automata-network/automata-tee-workload-measurem /** * @title Guardian module * @author Puffer Finance - * @dev This contract is responsible for storing enclave keys and validation of guardian's EOA/Enclave signatures + * @dev Manages a threshold-based guardian system that validates critical protocol operations using either + * EOA signatures or TEE session signatures from Automata's Session Registry. Guardians coordinate on + * validator provisioning, withdrawals, and ejections. * @custom:security-contact security@puffer.fi */ contract GuardianModule is AccessManaged, IGuardianModule { @@ -52,7 +54,7 @@ contract GuardianModule is AccessManaged, IGuardianModule { EnumerableSet.AddressSet private _guardians; /** - * @dev Threshold for the guardians + * @dev Threshold for the guardians. If the number of signatures/proofs is below this threshold, the action will not be authorized */ uint256 internal _threshold; @@ -286,6 +288,7 @@ contract GuardianModule is AccessManaged, IGuardianModule { * @dev Restricted to the DAO */ function setAllowedWorkload(bytes32 workloadId, bool allowed) external restricted { + require(workloadId != bytes32(0), WorkloadNotAllowed()); _allowedWorkloads[workloadId] = allowed; emit WorkloadAllowanceChanged(workloadId, allowed); } diff --git a/mainnet-contracts/src/interface/IGuardianModule.sol b/mainnet-contracts/src/interface/IGuardianModule.sol index 96b7b0ad..51f5dd7a 100644 --- a/mainnet-contracts/src/interface/IGuardianModule.sol +++ b/mainnet-contracts/src/interface/IGuardianModule.sol @@ -28,24 +28,6 @@ interface IGuardianModule { */ error InvalidThreshold(uint256 threshold); - /** - * @notice Thrown if the data is not valid - * @dev Signature "0x5cb045db" - */ - error InvalidData(); - - /** - * @notice Thrown if the GoldenMeasurement is not valid - * @dev Signature "0x69e9d3ba" - */ - error InvalidMeasurement(); - - /** - * @notice Thrown if the Commitment does not match the workload verifier - * @dev Signature "0x5054097b" - */ - error CommitmentMismatch(); - /** * @notice Thrown if the signature is not valid * @dev Signature "0x8baa579f" @@ -58,12 +40,6 @@ interface IGuardianModule { */ error WorkloadNotAllowed(); - /** - * @notice Thrown if the nonce is not valid - * @dev Signature "0x756688fe" - */ - error InvalidNonce(); - /** * @notice Emitted when the ejection threshold is changed * @param oldThreshold is the old threshold value @@ -94,14 +70,6 @@ interface IGuardianModule { */ event GuardianRemoved(address guardian); - /** - * @notice Emitted when the guardian changes guardian enclave address - * @param ownerFingerprint The fingerprint of the guardian's public key - * @param computedAddress The computed address from the new public key - * @dev Signature "0x6e41f97e85009a93fbd7a9e9c885b782819739d41a903d21bb4ad7a40d1af83a" - */ - event RotatedGuardianKey(bytes32 ownerFingerprint, address computedAddress); - /** * @notice Emitted when a workload allowance is changed * @param workloadId id of the workload diff --git a/mainnet-contracts/test/unit/GuardianModule.t.sol b/mainnet-contracts/test/unit/GuardianModule.t.sol index fc75dc32..95d5658d 100644 --- a/mainnet-contracts/test/unit/GuardianModule.t.sol +++ b/mainnet-contracts/test/unit/GuardianModule.t.sol @@ -123,6 +123,9 @@ contract GuardianModuleTest is UnitTestHelper { function test_setAllowedWorkload() public { vm.startPrank(DAO); + vm.expectRevert(abi.encodeWithSelector(IGuardianModule.WorkloadNotAllowed.selector)); + guardianModule.setAllowedWorkload(bytes32(0), true); + bytes32 workloadId = keccak256("test_workload"); // Initially workload should not be allowed From f8d9c75dea17de5ac71ff9330c593357dc08bce9 Mon Sep 17 00:00:00 2001 From: Eladio Date: Wed, 18 Feb 2026 13:30:15 +0100 Subject: [PATCH 28/51] Adapted addresses prior to hoodi deployment. Changed 0xddd => 0xeee --- mainnet-contracts/script/DeployPuffer.s.sol | 14 ++-- mainnet-contracts/script/DeployerHelper.s.sol | 64 +++++++++---------- ...GenerateBLSKeysAndRegisterValidators.s.sol | 2 +- .../test/helpers/UnitTestHelper.sol | 2 +- 4 files changed, 41 insertions(+), 41 deletions(-) diff --git a/mainnet-contracts/script/DeployPuffer.s.sol b/mainnet-contracts/script/DeployPuffer.s.sol index 63fa269c..e15bc95c 100644 --- a/mainnet-contracts/script/DeployPuffer.s.sol +++ b/mainnet-contracts/script/DeployPuffer.s.sol @@ -64,7 +64,7 @@ contract DeployPuffer is BaseScript { address eigenPodManager; address delegationManager; address rewardsCoordinator; - address eigenSlasher; + address allocationManager; address treasury; address operationsMultisig; @@ -79,7 +79,7 @@ contract DeployPuffer is BaseScript { // Mainnet / Mainnet fork eigenPodManager = 0x91E677b07F7AF907ec9a428aafA9fc14a0d3A338; delegationManager = 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A; - eigenSlasher = 0xD92145c07f8Ed1D392c1B88017934E301CC1c3Cd; + allocationManager = 0x948a420b8CC1d6BFd0B6087C2E7c344a2CD0bc39; rewardsCoordinator = address(0); //@todo treasury = vm.envAddress("TREASURY"); operationsMultisig = 0xC0896ab1A8cae8c2C1d27d011eb955Cca955580d; @@ -88,14 +88,14 @@ contract DeployPuffer is BaseScript { eigenPodManager = address(new EigenPodManagerMock()); delegationManager = address(new DelegationManagerMock()); rewardsCoordinator = address(new RewardsCoordinatorMock()); - eigenSlasher = address(new EigenAllocationManagerMock()); + allocationManager = address(new EigenAllocationManagerMock()); treasury = address(1); operationsMultisig = address(2); } else if (isHolesky()) { // Holesky https://github.com/Layr-Labs/eigenlayer-contracts?tab=readme-ov-file#current-testnet-deployment eigenPodManager = 0x30770d7E3e71112d7A6b7259542D1f680a70e315; delegationManager = 0xA44151489861Fe9e3055d95adC98FbD462B948e7; - eigenSlasher = 0xcAe751b75833ef09627549868A04E32679386e7C; + allocationManager = 0xcAe751b75833ef09627549868A04E32679386e7C; treasury = 0x61A44645326846F9b5d9c6f91AD27C3aD28EA390; rewardsCoordinator = 0xAcc1fb458a1317E886dB376Fc8141540537E68fE; operationsMultisig = 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; @@ -103,10 +103,10 @@ contract DeployPuffer is BaseScript { // Hoodi https://github.com/Layr-Labs/eigenlayer-contracts?tab=readme-ov-file#current-deployment-contracts eigenPodManager = 0xcd1442415Fc5C29Aa848A49d2e232720BE07976c; delegationManager = 0x867837a9722C512e0862d8c2E15b8bE220E8b87d; - eigenSlasher = 0xcAe751b75833ef09627549868A04E32679386e7C; // @todo Confirm EigenSlasher address + allocationManager = 0x95a7431400F362F3647a69535C5666cA0133CAA0; treasury = 0x61A44645326846F9b5d9c6f91AD27C3aD28EA390; rewardsCoordinator = 0x29e8572678e0c272350aa0b4B8f304E47EBcd5e7; - operationsMultisig = 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; + operationsMultisig = 0xeeE554b5b2bF5FBc9730Ce33c6dc92828DA01BeE; } else { revert("Deployment not configured for this chain"); } @@ -154,7 +154,7 @@ contract DeployPuffer is BaseScript { RestakingOperator restakingOperatorImplementation = new RestakingOperator( IDelegationManager(delegationManager), - IAllocationManager(eigenSlasher), + IAllocationManager(allocationManager), PufferModuleManager(payable(address(moduleManagerProxy))), IRewardsCoordinator(rewardsCoordinator), address(restakingOperatorController) diff --git a/mainnet-contracts/script/DeployerHelper.s.sol b/mainnet-contracts/script/DeployerHelper.s.sol index dc818d02..212fde7a 100644 --- a/mainnet-contracts/script/DeployerHelper.s.sol +++ b/mainnet-contracts/script/DeployerHelper.s.sol @@ -36,8 +36,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0 return 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0 - return 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; + // https://hoodi.etherscan.io/address/0xeeE554b5b2bF5FBc9730Ce33c6dc92828DA01BeE + return 0xeeE554b5b2bF5FBc9730Ce33c6dc92828DA01BeE; } else if (block.chainid == ape) { // https://apescan.io/address/0xb7d83623906AC3fa577F45B7D2b9D4BD26BC5d76 return 0xb7d83623906AC3fa577F45B7D2b9D4BD26BC5d76; @@ -166,8 +166,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x99c3E46E575df251149866285DdA7DAEba875B71 return 0x99c3E46E575df251149866285DdA7DAEba875B71; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0x9f9aa46c3b98aDDc1eEef87De25f986024f7C6Bb - return 0x9f9aa46c3b98aDDc1eEef87De25f986024f7C6Bb; + // https://hoodi.etherscan.io/address/??? // TODO + return address(0); } revert("RestakingOperatorBeacon not available for this chain"); @@ -198,8 +198,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x0910310130d1c062DEF8B807528bdac80203BC66 return 0x0910310130d1c062DEF8B807528bdac80203BC66; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0xF3654e122850Da267F4FA674BF96B671FF8EA216 - return 0xF3654e122850Da267F4FA674BF96B671FF8EA216; + // https://hoodi.etherscan.io/address/??? // TODO + return address(0); } revert("GuardianModule not available for this chain"); @@ -214,8 +214,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x4B0542470935ed4b085C3AD1983E85f5623ABf89 return 0x4B0542470935ed4b085C3AD1983E85f5623ABf89; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0x6F2BDD64A7ba1Ca06784f58D2dBaF3f54a010F49 - return 0x6F2BDD64A7ba1Ca06784f58D2dBaF3f54a010F49; + // https://hoodi.etherscan.io/address/??? // TODO + return address(0); } revert("PufferModuleBeacon not available for this chain"); @@ -262,8 +262,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x09BE86B01c1e32dCa2ebdEDb01cD5A3F798b80C5 return 0x09BE86B01c1e32dCa2ebdEDb01cD5A3F798b80C5; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0x66eb09811E1e46D60eD1421884E9FD76cbE555cA - return 0x66eb09811E1e46D60eD1421884E9FD76cbE555cA; + // https://hoodi.etherscan.io/address/??? // TODO + return address(0); } revert("AVSContractsRegistry not available for this chain"); @@ -278,8 +278,8 @@ abstract contract DeployerHelper is Script { // Holesky Timelock: https://explorer.pops.one/address/0x829aF0B3d099a12F0aE1b806f466EF771E2C07F8 return 0x829aF0B3d099a12F0aE1b806f466EF771E2C07F8; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0xA7A7C971B320f8B9F9557D49Ad5d988A668acD86 - return 0xA7A7C971B320f8B9F9557D49Ad5d988A668acD86; + // https://hoodi.etherscan.io/address/??? // TODO + return address(0); } revert("Timelock not available for this chain"); @@ -369,8 +369,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x8e043ed3F06720615685D4978770Cd5C8fe90fe3 return 0x8e043ed3F06720615685D4978770Cd5C8fe90fe3; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0x6d62a3520E47530cb9c1887b9C7FA4e6c2164027 - return 0x6d62a3520E47530cb9c1887b9C7FA4e6c2164027; + // https://hoodi.etherscan.io/address/??? // TODO + return address(0); } revert("puffer oracle not available for this chain"); @@ -401,8 +401,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x1d181cBd1825e9eBC6AD966878D555A7215FF4F0 return 0x1d181cBd1825e9eBC6AD966878D555A7215FF4F0; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0x6CeA393234314e5c12d017F46a5cc9555c79fAee - return 0x6CeA393234314e5c12d017F46a5cc9555c79fAee; + // https://hoodi.etherscan.io/address/??? // TODO + return address(0); } revert("WETH not available for this chain"); @@ -436,8 +436,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x180a345906e42293dcAd5CCD9b0e1DB26aE0274e return 0x180a345906e42293dcAd5CCD9b0e1DB26aE0274e; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0x9a86395B4c5B03a3D727A9037a122470adfA6F0e - return 0x9a86395B4c5B03a3D727A9037a122470adfA6F0e; + // https://hoodi.etherscan.io/address/??? // TODO + return address(0); } else if (block.chainid == binance) { // https://bscscan.com/address/0x8849e9eB8bb27c1916AfB17ee4dEcAd375916474 return 0x8849e9eB8bb27c1916AfB17ee4dEcAd375916474; @@ -465,8 +465,8 @@ abstract contract DeployerHelper is Script { // https://sepolia.etherscan.io/address/0xd85D701A660a61D9737D05397612EF08be2cE62D return 0xd85D701A660a61D9737D05397612EF08be2cE62D; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0x5D5F97aAeb0c802C82B6E2d0C876CEc9C51cB1D1 - return 0x5D5F97aAeb0c802C82B6E2d0C876CEc9C51cB1D1; + // https://hoodi.etherscan.io/address/??? // TODO + return address(0); } revert("PufferVault not available for this chain"); @@ -481,8 +481,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x20377c306451140119C9967Ba6D0158a05b4eD07 return 0x20377c306451140119C9967Ba6D0158a05b4eD07; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0x4a143618836f8bb84B328654f75d6C130500e375 - return 0x4a143618836f8bb84B328654f75d6C130500e375; + // https://hoodi.etherscan.io/address/??? // TODO + return address(0); } revert("PufferModuleManager not available for this chain"); @@ -497,8 +497,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0xB028194785178a94Fe608994A4d5AD84c285A640 return 0xB028194785178a94Fe608994A4d5AD84c285A640; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0x34E70AcAEa2046F1c9E27894Ed8E05535A44DD41 - return 0x34E70AcAEa2046F1c9E27894Ed8E05535A44DD41; + // https://hoodi.etherscan.io/address/??? // TODO + return address(0); } revert("ValidatorTicket not available for this chain"); @@ -513,8 +513,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0xE00c79408B9De5BaD2FDEbB1688997a68eC988CD return 0xE00c79408B9De5BaD2FDEbB1688997a68eC988CD; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0x7dE52e679e82395CB62C5B574A81cef637529fba - return 0x7dE52e679e82395CB62C5B574A81cef637529fba; + // https://hoodi.etherscan.io/address/??? // TODO + return address(0); } revert("PufferProtocol not available for this chain"); @@ -529,8 +529,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/- return address(0); } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0x9C47BFa23E26d88b1F43c5EBA2CDb25fEF359ed1 - return 0x9C47BFa23E26d88b1F43c5EBA2CDb25fEF359ed1; + // https://hoodi.etherscan.io/address/??? // TODO + return address(0); } revert("RestakingOperatorController not available for this chain"); @@ -663,8 +663,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0 return 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0 - return 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; + // https://hoodi.etherscan.io/address/0xeeE554b5b2bF5FBc9730Ce33c6dc92828DA01BeE + return 0xeeE554b5b2bF5FBc9730Ce33c6dc92828DA01BeE; } revert("Paymaster not available for this chain"); @@ -703,8 +703,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0 return 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0 - return 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; + // https://hoodi.etherscan.io/address/0xeeE554b5b2bF5FBc9730Ce33c6dc92828DA01BeE + return 0xeeE554b5b2bF5FBc9730Ce33c6dc92828DA01BeE; } else if (block.chainid == ape) { // https://apescan.io/address/0x36E3881Ff855c264045c22179b6fBc01430F97EC return 0x36E3881Ff855c264045c22179b6fBc01430F97EC; diff --git a/mainnet-contracts/script/GenerateBLSKeysAndRegisterValidators.s.sol b/mainnet-contracts/script/GenerateBLSKeysAndRegisterValidators.s.sol index 62e2945d..ad1c0f62 100644 --- a/mainnet-contracts/script/GenerateBLSKeysAndRegisterValidators.s.sol +++ b/mainnet-contracts/script/GenerateBLSKeysAndRegisterValidators.s.sol @@ -45,7 +45,7 @@ contract GenerateBLSKeysAndRegisterValidators is Script { forkVersion = "0x01017000"; } else if (block.chainid == 560048) { // Hoodi - protocolAddress = 0x7dE52e679e82395CB62C5B574A81cef637529fba; + protocolAddress = address(0); // TODO pufferProtocol = PufferProtocol(protocolAddress); forkVersion = "0x10000910"; } else if (block.chainid == 1) { diff --git a/mainnet-contracts/test/helpers/UnitTestHelper.sol b/mainnet-contracts/test/helpers/UnitTestHelper.sol index 7532a055..039560d4 100644 --- a/mainnet-contracts/test/helpers/UnitTestHelper.sol +++ b/mainnet-contracts/test/helpers/UnitTestHelper.sol @@ -278,7 +278,7 @@ contract UnitTestHelper is Test, BaseScript { vm.label(address(pufferDepositor), "PufferDepositor"); vm.label(address(pufferProtocol), "PufferProtocol"); - // No longer enclave adrresses in GuardianModule + // Populate the session registry with the guardians' session and owner public identities guardian1OwnerPublicIdentity = PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian1OwnerPubKey }); guardian2OwnerPublicIdentity = PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian2OwnerPubKey }); guardian3OwnerPublicIdentity = PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian3OwnerPubKey }); From 241a5d73a77c05296d200ce8b56d4d929c158592 Mon Sep 17 00:00:00 2001 From: Eladio Date: Wed, 18 Feb 2026 18:44:48 +0100 Subject: [PATCH 29/51] Updated hoodi deployment addresses --- mainnet-contracts/script/DeployerHelper.s.sol | 52 +++++++++---------- ...GenerateBLSKeysAndRegisterValidators.s.sol | 2 +- .../PufferModuleManager.integration.t.sol | 13 +++-- ...fferModuleManagerSlasher.integration.t.sol | 6 +-- .../ffi/PufferModuleManagerHoodiFfi.t.sol | 12 ++--- .../test/helpers/IntegrationTestHelper.sol | 8 +-- .../test/unit/PufferProtocol.t.sol | 2 +- 7 files changed, 49 insertions(+), 46 deletions(-) diff --git a/mainnet-contracts/script/DeployerHelper.s.sol b/mainnet-contracts/script/DeployerHelper.s.sol index 212fde7a..262c526f 100644 --- a/mainnet-contracts/script/DeployerHelper.s.sol +++ b/mainnet-contracts/script/DeployerHelper.s.sol @@ -166,8 +166,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x99c3E46E575df251149866285DdA7DAEba875B71 return 0x99c3E46E575df251149866285DdA7DAEba875B71; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? // TODO - return address(0); + // https://hoodi.etherscan.io/address/0x6a5c73AB3e5Bc3675A2e1CCcc46aF6796db36BC8 + return 0x6a5c73AB3e5Bc3675A2e1CCcc46aF6796db36BC8; } revert("RestakingOperatorBeacon not available for this chain"); @@ -198,8 +198,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x0910310130d1c062DEF8B807528bdac80203BC66 return 0x0910310130d1c062DEF8B807528bdac80203BC66; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? // TODO - return address(0); + // https://hoodi.etherscan.io/address/0x57bC9fDcd05bD53bCe1B2db3a50Eb5948Bd4e5c7 + return 0x57bC9fDcd05bD53bCe1B2db3a50Eb5948Bd4e5c7; } revert("GuardianModule not available for this chain"); @@ -214,8 +214,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x4B0542470935ed4b085C3AD1983E85f5623ABf89 return 0x4B0542470935ed4b085C3AD1983E85f5623ABf89; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? // TODO - return address(0); + // https://hoodi.etherscan.io/address/0x6899d0dE991458929b43e3DE4fC2d4A9ca7E4673 + return 0x6899d0dE991458929b43e3DE4fC2d4A9ca7E4673; } revert("PufferModuleBeacon not available for this chain"); @@ -262,8 +262,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x09BE86B01c1e32dCa2ebdEDb01cD5A3F798b80C5 return 0x09BE86B01c1e32dCa2ebdEDb01cD5A3F798b80C5; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? // TODO - return address(0); + // https://hoodi.etherscan.io/address/0x5150F12A6f5a3D071A84442a671a4B234B53beC4 + return 0x5150F12A6f5a3D071A84442a671a4B234B53beC4; } revert("AVSContractsRegistry not available for this chain"); @@ -278,8 +278,8 @@ abstract contract DeployerHelper is Script { // Holesky Timelock: https://explorer.pops.one/address/0x829aF0B3d099a12F0aE1b806f466EF771E2C07F8 return 0x829aF0B3d099a12F0aE1b806f466EF771E2C07F8; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? // TODO - return address(0); + // https://hoodi.etherscan.io/address/0xD256D160598ba8e068fC62C7fED46694CdD48762 + return 0xD256D160598ba8e068fC62C7fED46694CdD48762; } revert("Timelock not available for this chain"); @@ -369,8 +369,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x8e043ed3F06720615685D4978770Cd5C8fe90fe3 return 0x8e043ed3F06720615685D4978770Cd5C8fe90fe3; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? // TODO - return address(0); + // https://hoodi.etherscan.io/address/0xF232Df3a714c99C05100571644b6d4AA1000ee4E + return 0xF232Df3a714c99C05100571644b6d4AA1000ee4E; } revert("puffer oracle not available for this chain"); @@ -401,8 +401,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x1d181cBd1825e9eBC6AD966878D555A7215FF4F0 return 0x1d181cBd1825e9eBC6AD966878D555A7215FF4F0; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? // TODO - return address(0); + // https://hoodi.etherscan.io/address/0x06EDa6073b3dE1B1Dfd58cb5615fD8188C114a88 + return 0x06EDa6073b3dE1B1Dfd58cb5615fD8188C114a88; } revert("WETH not available for this chain"); @@ -436,8 +436,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x180a345906e42293dcAd5CCD9b0e1DB26aE0274e return 0x180a345906e42293dcAd5CCD9b0e1DB26aE0274e; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? // TODO - return address(0); + // https://hoodi.etherscan.io/address/0x0950195ac9b310815698f5dded3bd32814f46efd + return 0x0950195ac9b310815698f5dded3bd32814f46efd; } else if (block.chainid == binance) { // https://bscscan.com/address/0x8849e9eB8bb27c1916AfB17ee4dEcAd375916474 return 0x8849e9eB8bb27c1916AfB17ee4dEcAd375916474; @@ -465,8 +465,8 @@ abstract contract DeployerHelper is Script { // https://sepolia.etherscan.io/address/0xd85D701A660a61D9737D05397612EF08be2cE62D return 0xd85D701A660a61D9737D05397612EF08be2cE62D; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? // TODO - return address(0); + // https://hoodi.etherscan.io/address/0x3248c7b9D2c8e427A2752cA2339166830FA83479 + return 0x3248c7b9D2c8e427A2752cA2339166830FA83479; } revert("PufferVault not available for this chain"); @@ -481,8 +481,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x20377c306451140119C9967Ba6D0158a05b4eD07 return 0x20377c306451140119C9967Ba6D0158a05b4eD07; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? // TODO - return address(0); + // https://hoodi.etherscan.io/address/0x26eEa064e7Ed6b52847f8153Cd466A7b01f2cB14 + return 0x26eEa064e7Ed6b52847f8153Cd466A7b01f2cB14; } revert("PufferModuleManager not available for this chain"); @@ -497,8 +497,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0xB028194785178a94Fe608994A4d5AD84c285A640 return 0xB028194785178a94Fe608994A4d5AD84c285A640; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? // TODO - return address(0); + // https://hoodi.etherscan.io/address/0x032E3fF6716084Bd8D50a35f1cfC9a22cEeB0355 + return 0x032E3fF6716084Bd8D50a35f1cfC9a22cEeB0355; } revert("ValidatorTicket not available for this chain"); @@ -513,8 +513,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0xE00c79408B9De5BaD2FDEbB1688997a68eC988CD return 0xE00c79408B9De5BaD2FDEbB1688997a68eC988CD; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? // TODO - return address(0); + // https://hoodi.etherscan.io/address/0xa3eca8ef718538Fc2610899e95590B521D59a842 + return 0xa3eca8ef718538Fc2610899e95590B521D59a842; } revert("PufferProtocol not available for this chain"); @@ -529,8 +529,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/- return address(0); } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/??? // TODO - return address(0); + // https://hoodi.etherscan.io/address/0xa3eca8ef718538Fc2610899e95590B521D59a842 + return 0xa3eca8ef718538Fc2610899e95590B521D59a842; } revert("RestakingOperatorController not available for this chain"); diff --git a/mainnet-contracts/script/GenerateBLSKeysAndRegisterValidators.s.sol b/mainnet-contracts/script/GenerateBLSKeysAndRegisterValidators.s.sol index ad1c0f62..5a9216b2 100644 --- a/mainnet-contracts/script/GenerateBLSKeysAndRegisterValidators.s.sol +++ b/mainnet-contracts/script/GenerateBLSKeysAndRegisterValidators.s.sol @@ -45,7 +45,7 @@ contract GenerateBLSKeysAndRegisterValidators is Script { forkVersion = "0x01017000"; } else if (block.chainid == 560048) { // Hoodi - protocolAddress = address(0); // TODO + protocolAddress = 0xa3eca8ef718538Fc2610899e95590B521D59a842; pufferProtocol = PufferProtocol(protocolAddress); forkVersion = "0x10000910"; } else if (block.chainid == 1) { diff --git a/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol b/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol index 1a3992ae..6d5f2270 100644 --- a/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol +++ b/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol @@ -30,7 +30,10 @@ contract PufferModuleManagerIntegrationTest is IntegrationTestHelper { address EIGEN_DA_SERVICE_MANAGER = 0x3FF2204A567C15dC3731140B95362ABb4b17d8ED; // IAVSDirectory public avsDirectory = IAVSDirectory(0x055733000064333CaDDbC92763c58BF0192fFeBf); - address private constant HOODI_WETH_ADDRESS = 0x6CeA393234314e5c12d017F46a5cc9555c79fAee; + address private constant HOODI_WETH_ADDRESS = 0x06EDa6073b3dE1B1Dfd58cb5615fD8188C114a88; + address private constant HOODI_STRATEGY_MANAGER = 0xeE45e76ddbEDdA2918b8C7E3035cd37Eab3b5D41; + address private constant HOODI_WETH_STRATEGY = 0x24579aD4fe83aC53546E5c2D3dF5F85D6383420d; + address private constant HOODI_DELEGATION_MANAGER = 0x867837a9722C512e0862d8c2E15b8bE220E8b87d; function setUp() public { deployContractsHoodi(0); // on latest block @@ -45,14 +48,14 @@ contract PufferModuleManagerIntegrationTest is IntegrationTestHelper { // buy weth vm.startPrank(0xA85Fdcb45aaFF3C310a47FE309D4a35FAfbdc0ad); // TODO Change Weth(HOODI_WETH_ADDRESS).deposit{ value: 500 ether }(); - Weth(HOODI_WETH_ADDRESS).approve(0xeE45e76ddbEDdA2918b8C7E3035cd37Eab3b5D41, type(uint256).max); + Weth(HOODI_WETH_ADDRESS).approve(HOODI_STRATEGY_MANAGER, type(uint256).max); // deposit into weth strategy - IStrategyManager(0xeE45e76ddbEDdA2918b8C7E3035cd37Eab3b5D41).depositIntoStrategy( - IStrategy(0x24579aD4fe83aC53546E5c2D3dF5F85D6383420d), IERC20(HOODI_WETH_ADDRESS), 500 ether + IStrategyManager(HOODI_STRATEGY_MANAGER).depositIntoStrategy( + IStrategy(HOODI_WETH_STRATEGY), IERC20(HOODI_WETH_ADDRESS), 500 ether ); ISignatureUtils.SignatureWithExpiry memory signatureWithExpiry; - IDelegationManager(0x867837a9722C512e0862d8c2E15b8bE220E8b87d).delegateTo( + IDelegationManager(HOODI_DELEGATION_MANAGER).delegateTo( restakingOperator, signatureWithExpiry, bytes32(0) ); } diff --git a/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol b/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol index e47523f5..64176e3a 100644 --- a/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol +++ b/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol @@ -19,9 +19,9 @@ import { RestakingOperatorController } from "../../src/RestakingOperatorControll contract PufferModuleManagerSlasherIntegrationTest is Test, DeployerHelper { PufferModuleManager public pufferModuleManager; - address PUFFER_MODULE_0_HOODI = 0x1C898d25BC7B2819E8F0Af53A5a956F071f971fF; - address EIGENPOD_0_HOODI = 0xE7FDd7769f369cd1534Cb727A812Bce04553b24d; - address RESTAKING_OPERATOR_0_HOODI = 0x57b6FdEF3A23B81547df68F44e5524b987755c99; // TODO Change + address PUFFER_MODULE_0_HOODI = 0xeaA758DC50180ac70Ec69A241f8a866e6e852905; + address EIGENPOD_0_HOODI = 0x17F9D0ffAAeF968d2c44807Cf3c96D504e640cA8; + address RESTAKING_OPERATOR_0_HOODI = address(0); // TODO Change bytes32 PUFFER_MODULE_0_NAME = bytes32("PUFFER_MODULE_0"); DeployPufferModuleManager deployPufferModuleManager; diff --git a/mainnet-contracts/test/fork-tests/ffi/PufferModuleManagerHoodiFfi.t.sol b/mainnet-contracts/test/fork-tests/ffi/PufferModuleManagerHoodiFfi.t.sol index db85c130..838787e7 100644 --- a/mainnet-contracts/test/fork-tests/ffi/PufferModuleManagerHoodiFfi.t.sol +++ b/mainnet-contracts/test/fork-tests/ffi/PufferModuleManagerHoodiFfi.t.sol @@ -27,12 +27,12 @@ contract PufferModuleManagerHoodiTestnetFFI is Test { address DELEGATION_MANAGER = 0x867837a9722C512e0862d8c2E15b8bE220E8b87d; // Puffer Hoodi deployment - address PUFFER_SHARED_DEV_WALLET = 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; - address ACCESS_MANAGER_HOODI = 0x9a86395B4c5B03a3D727A9037a122470adfA6F0e; - address MODULE_BEACON_HOODI = 0x6F2BDD64A7ba1Ca06784f58D2dBaF3f54a010F49; - address PUFFER_PROTOCOL_HOODI = 0x7dE52e679e82395CB62C5B574A81cef637529fba; - address PUFFER_MODULE_MANAGER = 0x4a143618836f8bb84B328654f75d6C130500e375; - address PUFFER_MODULE_0_HOODI = 0x1C898d25BC7B2819E8F0Af53A5a956F071f971fF; + address PUFFER_SHARED_DEV_WALLET = 0xeeE554b5b2bF5FBc9730Ce33c6dc92828DA01BeE; + address ACCESS_MANAGER_HOODI = 0x0950195ac9b310815698f5dded3bd32814f46efd; + address MODULE_BEACON_HOODI = 0x6899d0dE991458929b43e3DE4fC2d4A9ca7E4673; + address PUFFER_PROTOCOL_HOODI = 0xa3eca8ef718538Fc2610899e95590B521D59a842; + address PUFFER_MODULE_MANAGER = 0x26eEa064e7Ed6b52847f8153Cd466A7b01f2cB14; + address PUFFER_MODULE_0_HOODI = 0xeaA758DC50180ac70Ec69A241f8a866e6e852905; // https://hoodi.eigenlayer.xyz/operator/0xe2c2dc296a0bff351f6bc3e98d37ea798e393e56 // TODO Change address RESTAKING_OPERATOR_CONTRACT = 0xe2c2dc296a0bFF351F6bC3e98D37ea798e393e56; // TODO Change address RESTAKING_OPERATOR_BEACON = 0x9f9aa46c3b98aDDc1eEef87De25f986024f7C6Bb; diff --git a/mainnet-contracts/test/helpers/IntegrationTestHelper.sol b/mainnet-contracts/test/helpers/IntegrationTestHelper.sol index 7df4007b..d48eb374 100644 --- a/mainnet-contracts/test/helpers/IntegrationTestHelper.sol +++ b/mainnet-contracts/test/helpers/IntegrationTestHelper.sol @@ -14,7 +14,7 @@ import { ISessionRegistry } from "@automata-network/automata-tee-workload-measurement/interfaces/registries/ISessionRegistry.sol"; contract IntegrationTestHelper is Test { - address DAO = 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; + address DAO = 0xeeE554b5b2bF5FBc9730Ce33c6dc92828DA01BeE; PufferProtocol public pufferProtocol; UpgradeableBeacon public beacon; PufferModuleManager public moduleManager; @@ -26,8 +26,8 @@ contract IntegrationTestHelper is Test { ISessionRegistry public sessionRegistry; bytes32 PUFFER_MODULE_0 = bytes32("PUFFER_MODULE_0"); - address PAYMASTER = 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0; - address SESSION_REGISTRY = address(0); //TODO [TDX] Set the address of the session registry + address PAYMASTER = 0xeeE554b5b2bF5FBc9730Ce33c6dc92828DA01BeE; + address SESSION_REGISTRY = 0xD1860020870ffEd23a644d0CD4CA9E7b3Ff53D6c; // custom block number function deployContractsHoodi(uint256 blockNumber) public virtual { @@ -46,7 +46,7 @@ contract IntegrationTestHelper is Test { // 'default' block number function deployContractsHoodi() public virtual { - deployContractsHoodi(1_212_252); // TODO Change + deployContractsHoodi(2_260_721); } function _deployAndLabel(address[] memory guardians, uint256 threshold) internal { diff --git a/mainnet-contracts/test/unit/PufferProtocol.t.sol b/mainnet-contracts/test/unit/PufferProtocol.t.sol index 322c16ef..0de28a05 100644 --- a/mainnet-contracts/test/unit/PufferProtocol.t.sol +++ b/mainnet-contracts/test/unit/PufferProtocol.t.sol @@ -77,7 +77,7 @@ contract PufferProtocolTest is UnitTestHelper { // Fund no restaking module with 200 ETH vm.deal(NoRestakingModule, 200 ether); - // TODO Set allowed workload in GuardianModule and sessionRegistry mock + // Set allowed workload in GuardianModule and sessionRegistry mock bytes32 workload1 = keccak256("workload1"); bytes32 workload2 = keccak256("workload2"); bytes32 workload3 = keccak256("workload3"); From 7d8679dc87686db269c942ad7247a14b756403e5 Mon Sep 17 00:00:00 2001 From: eladiosch <3090613+eladiosch@users.noreply.github.com> Date: Thu, 19 Feb 2026 08:47:16 +0000 Subject: [PATCH 30/51] forge fmt --- mainnet-contracts/script/DeployerHelper.s.sol | 2 +- .../test/fork-tests/PufferModuleManager.integration.t.sol | 4 +--- .../test/fork-tests/ffi/PufferModuleManagerHoodiFfi.t.sol | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/mainnet-contracts/script/DeployerHelper.s.sol b/mainnet-contracts/script/DeployerHelper.s.sol index 262c526f..280bc340 100644 --- a/mainnet-contracts/script/DeployerHelper.s.sol +++ b/mainnet-contracts/script/DeployerHelper.s.sol @@ -437,7 +437,7 @@ abstract contract DeployerHelper is Script { return 0x180a345906e42293dcAd5CCD9b0e1DB26aE0274e; } else if (block.chainid == hoodi) { // https://hoodi.etherscan.io/address/0x0950195ac9b310815698f5dded3bd32814f46efd - return 0x0950195ac9b310815698f5dded3bd32814f46efd; + return 0x0950195AC9B310815698f5dDeD3BD32814f46EFD; } else if (block.chainid == binance) { // https://bscscan.com/address/0x8849e9eB8bb27c1916AfB17ee4dEcAd375916474 return 0x8849e9eB8bb27c1916AfB17ee4dEcAd375916474; diff --git a/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol b/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol index 6d5f2270..c0c6197e 100644 --- a/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol +++ b/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol @@ -55,9 +55,7 @@ contract PufferModuleManagerIntegrationTest is IntegrationTestHelper { ); ISignatureUtils.SignatureWithExpiry memory signatureWithExpiry; - IDelegationManager(HOODI_DELEGATION_MANAGER).delegateTo( - restakingOperator, signatureWithExpiry, bytes32(0) - ); + IDelegationManager(HOODI_DELEGATION_MANAGER).delegateTo(restakingOperator, signatureWithExpiry, bytes32(0)); } // Creates a new restaking operator and returns it diff --git a/mainnet-contracts/test/fork-tests/ffi/PufferModuleManagerHoodiFfi.t.sol b/mainnet-contracts/test/fork-tests/ffi/PufferModuleManagerHoodiFfi.t.sol index 838787e7..dbf12733 100644 --- a/mainnet-contracts/test/fork-tests/ffi/PufferModuleManagerHoodiFfi.t.sol +++ b/mainnet-contracts/test/fork-tests/ffi/PufferModuleManagerHoodiFfi.t.sol @@ -28,7 +28,7 @@ contract PufferModuleManagerHoodiTestnetFFI is Test { // Puffer Hoodi deployment address PUFFER_SHARED_DEV_WALLET = 0xeeE554b5b2bF5FBc9730Ce33c6dc92828DA01BeE; - address ACCESS_MANAGER_HOODI = 0x0950195ac9b310815698f5dded3bd32814f46efd; + address ACCESS_MANAGER_HOODI = 0x0950195AC9B310815698f5dDeD3BD32814f46EFD; address MODULE_BEACON_HOODI = 0x6899d0dE991458929b43e3DE4fC2d4A9ca7E4673; address PUFFER_PROTOCOL_HOODI = 0xa3eca8ef718538Fc2610899e95590B521D59a842; address PUFFER_MODULE_MANAGER = 0x26eEa064e7Ed6b52847f8153Cd466A7b01f2cB14; From 300d388bf1db11fddde7139c18d3d9462475c911 Mon Sep 17 00:00:00 2001 From: Eladio Date: Thu, 19 Feb 2026 18:04:09 +0100 Subject: [PATCH 31/51] Fixed _deployRevenueDepositor --- mainnet-contracts/script/DeployEverything.s.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mainnet-contracts/script/DeployEverything.s.sol b/mainnet-contracts/script/DeployEverything.s.sol index b34030e4..ee0da489 100644 --- a/mainnet-contracts/script/DeployEverything.s.sol +++ b/mainnet-contracts/script/DeployEverything.s.sol @@ -108,6 +108,7 @@ contract DeployEverything is BaseScript { // script/DeployRevenueDepositor.s.sol It should match the one in the script function _deployRevenueDepositor(PufferDeployment memory puffETHDeployment) internal returns (address) { + vm.startBroadcast(); MockAeraVault mockAeraVault = new MockAeraVault(); PufferRevenueDepositor revenueDepositorImpl = new PufferRevenueDepositor({ @@ -126,6 +127,7 @@ contract DeployEverything is BaseScript { ) ) ); + vm.stopBroadcast(); bytes memory accessManagerCd = new GenerateRevenueDepositorCalldata().run(address(revenueDepositor), makeAddr("operationsMultisig")); From 422c2909e0dd03662010235eda0b34dd98a12aa5 Mon Sep 17 00:00:00 2001 From: Eladio Date: Mon, 23 Feb 2026 09:47:17 +0100 Subject: [PATCH 32/51] Minor updated to deployment scripts --- mainnet-contracts/script/DeployRevenueDepositor.s.sol | 2 +- mainnet-contracts/script/DeployerHelper.s.sol | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/mainnet-contracts/script/DeployRevenueDepositor.s.sol b/mainnet-contracts/script/DeployRevenueDepositor.s.sol index da679499..49c3a909 100644 --- a/mainnet-contracts/script/DeployRevenueDepositor.s.sol +++ b/mainnet-contracts/script/DeployRevenueDepositor.s.sol @@ -45,7 +45,7 @@ contract DeployRevenueDepositor is DeployerHelper { console.log("Queue from Timelock -> AccessManager", _getAccessManager()); console.logBytes(encodedCalldata); - if (block.chainid == holesky) { + if (block.chainid == holesky || block.chainid == hoodi) { (bool success,) = address(_getAccessManager()).call(encodedCalldata); require(success, "AccessManager.call failed"); } diff --git a/mainnet-contracts/script/DeployerHelper.s.sol b/mainnet-contracts/script/DeployerHelper.s.sol index 280bc340..58616180 100644 --- a/mainnet-contracts/script/DeployerHelper.s.sol +++ b/mainnet-contracts/script/DeployerHelper.s.sol @@ -753,6 +753,9 @@ abstract contract DeployerHelper is Script { if (block.chainid == mainnet) { // https://etherscan.io/address/0x21660F4681aD5B6039007f7006b5ab0EF9dE7882 return 0x21660F4681aD5B6039007f7006b5ab0EF9dE7882; + } else if (block.chainid == hoodi) { + // https://hoodi.etherscan.io/address/0x8cafCc00DC0c10404a246Fa261428Df630374392 + return 0x8cafCc00DC0c10404a246Fa261428Df630374392; } revert("RevenueDepositor not available for this chain"); From c61024a29a9eb5550d720830079ede9675c2168f Mon Sep 17 00:00:00 2001 From: Eladio Date: Mon, 2 Mar 2026 11:01:06 +0100 Subject: [PATCH 33/51] Adapting changes to new tdx [WIP] --- .../script/DeployEverything.s.sol | 19 +- .../script/DeployGuardians.s.sol | 6 +- mainnet-contracts/src/GuardianModule.sol | 196 +++++++++++------- mainnet-contracts/src/PufferProtocol.sol | 19 +- .../src/interface/IGuardianModule.sol | 71 +++++-- .../src/interface/IPufferProtocol.sol | 4 +- .../test/handlers/PufferProtocolHandler.sol | 55 ++--- .../test/helpers/IntegrationTestHelper.sol | 4 +- .../test/helpers/UnitTestHelper.sol | 6 +- .../test/unit/PufferProtocol.t.sol | 183 ++++++---------- 10 files changed, 295 insertions(+), 268 deletions(-) diff --git a/mainnet-contracts/script/DeployEverything.s.sol b/mainnet-contracts/script/DeployEverything.s.sol index ee0da489..fe30075c 100644 --- a/mainnet-contracts/script/DeployEverything.s.sol +++ b/mainnet-contracts/script/DeployEverything.s.sol @@ -24,15 +24,18 @@ import { ISessionRegistry } from * @author Puffer Finance * @notice Deploys pufETH (upgrade it in test environment), Guardians, Oracle, Puffer, and sets up the access control * @dev Example on how to run the script - * forge script script/DeployEverything.s.sol:DeployEverything --rpc-url=$RPC_URL --sig 'run(address, address[] calldata, uint256, address)' "[$DEV_WALLET]" 1 $DEV_WALLET --broadcast + * forge script script/DeployEverything.s.sol:DeployEverything --rpc-url=$RPC_URL --sig 'run(address, address[] calldata, uint256, address, uint256)' "[$DEV_WALLET]" 1 $DEV_WALLET $FRESHNESS_BLOCKS --broadcast */ contract DeployEverything is BaseScript { address DAO; - function run(address sessionRegistry, address[] calldata guardians, uint256 threshold, address paymaster) - public - returns (PufferProtocolDeployment memory, BridgingDeployment memory) - { + function run( + address sessionRegistry, + address[] calldata guardians, + uint256 threshold, + address paymaster, + uint256 freshnessBlocks + ) public returns (PufferProtocolDeployment memory, BridgingDeployment memory) { PufferProtocolDeployment memory deployment; // 1. Deploy pufETH @@ -47,7 +50,11 @@ contract DeployEverything is BaseScript { deployment.accessManager = puffETHDeployment.accessManager; GuardiansDeployment memory guardiansDeployment = new DeployGuardians().run( - ISessionRegistry(sessionRegistry), AccessManager(puffETHDeployment.accessManager), guardians, threshold + ISessionRegistry(sessionRegistry), + AccessManager(puffETHDeployment.accessManager), + guardians, + threshold, + freshnessBlocks ); address pufferOracle = new DeployPufferOracle().run( diff --git a/mainnet-contracts/script/DeployGuardians.s.sol b/mainnet-contracts/script/DeployGuardians.s.sol index bb45ca6c..9641365a 100644 --- a/mainnet-contracts/script/DeployGuardians.s.sol +++ b/mainnet-contracts/script/DeployGuardians.s.sol @@ -14,11 +14,13 @@ contract DeployGuardians is BaseScript { ISessionRegistry sessionRegistry, AccessManager accessManager, address[] calldata guardians, - uint256 threshold + uint256 threshold, + uint256 freshnessBlocks ) public broadcast returns (GuardiansDeployment memory) { vm.label(address(accessManager), "AccessManager"); - GuardianModule module = new GuardianModule(sessionRegistry, guardians, threshold, address(accessManager)); + GuardianModule module = + new GuardianModule(sessionRegistry, guardians, threshold, address(accessManager), freshnessBlocks); GuardiansDeployment memory deployment; deployment.accessManager = address(accessManager); diff --git a/mainnet-contracts/src/GuardianModule.sol b/mainnet-contracts/src/GuardianModule.sol index 378b7e55..95527cb7 100644 --- a/mainnet-contracts/src/GuardianModule.sol +++ b/mainnet-contracts/src/GuardianModule.sol @@ -21,9 +21,7 @@ import { ALGO_ID_ES256K } from "@automata-network/automata-tee-workload-measurem /** * @title Guardian module * @author Puffer Finance - * @dev Manages a threshold-based guardian system that validates critical protocol operations using either - * EOA signatures or TEE session signatures from Automata's Session Registry. Guardians coordinate on - * validator provisioning, withdrawals, and ejections. + * @dev This contract is responsible for storing enclave keys and validation of guardian's EOA/Enclave signatures * @custom:security-contact security@puffer.fi */ contract GuardianModule is AccessManaged, IGuardianModule { @@ -43,6 +41,11 @@ contract GuardianModule is AccessManaged, IGuardianModule { */ uint256 internal constant _EJECTION_THRESHOLD_BALANCE = 31.75 ether; + /** + * @notice Freshness number of blocks + */ + uint256 public immutable FRESHNESS_BLOCKS; + /** * @notice Session Registry smart contract */ @@ -54,7 +57,7 @@ contract GuardianModule is AccessManaged, IGuardianModule { EnumerableSet.AddressSet private _guardians; /** - * @dev Threshold for the guardians. If the number of signatures/proofs is below this threshold, the action will not be authorized + * @dev Threshold for the guardians */ uint256 internal _threshold; @@ -63,6 +66,20 @@ contract GuardianModule is AccessManaged, IGuardianModule { */ uint256 internal _ejectionThreshold; + /** + * @dev Enclave data + * The guardian doesn't know the Secret Key of an enclave wallet + */ + struct GuardianData { + bytes enclavePubKey; + address enclaveAddress; + } + + /** + * @dev Mapping of a Guardian's EOA to enclave data + */ + mapping(address guardian => GuardianData data) internal _guardianEnclaves; + /** * @dev Mapping of allowed workload IDs (can be added/removed) */ @@ -72,7 +89,8 @@ contract GuardianModule is AccessManaged, IGuardianModule { ISessionRegistry sessionRegistry, address[] memory guardians, uint256 threshold, - address pufferAuthority + address pufferAuthority, + uint256 freshnessBlocks ) payable AccessManaged(pufferAuthority) { if (address(sessionRegistry) == address(0)) { revert InvalidAddress(); @@ -86,6 +104,8 @@ contract GuardianModule is AccessManaged, IGuardianModule { } _setEjectionThreshold(_EJECTION_THRESHOLD_BALANCE); _setThreshold(threshold); + + FRESHNESS_BLOCKS = freshnessBlocks; } receive() external payable { } @@ -136,7 +156,7 @@ contract GuardianModule is AccessManaged, IGuardianModule { bytes calldata signature, bytes calldata withdrawalCredentials, bytes32 depositDataRoot, - GuardianSessionProof[] calldata guardianProofs + bytes[] calldata enclaveSignatures ) external view { // Recreate the message hash bytes32 signedMessageHash = LibGuardianMessages._getBeaconDepositMessageToBeSigned({ @@ -147,8 +167,13 @@ contract GuardianModule is AccessManaged, IGuardianModule { depositDataRoot: depositDataRoot }); - bool validSessionProofs = validateSessionProofs(guardianProofs, signedMessageHash); - if (!validSessionProofs) { + // Check the signatures + bool validSignatures = validateGuardiansEnclaveSignatures({ + enclaveSignatures: enclaveSignatures, + signedMessageHash: signedMessageHash + }); + + if (!validSignatures) { revert Unauthorized(); } } @@ -206,73 +231,12 @@ contract GuardianModule is AccessManaged, IGuardianModule { /** * @inheritdoc IGuardianModule */ - function validateSessionProofs(GuardianSessionProof[] calldata guardianProofs, bytes32 signedMessageHash) + function validateGuardiansEnclaveSignatures(bytes[] calldata enclaveSignatures, bytes32 signedMessageHash) public view returns (bool) { - uint256 threshold = _threshold; - uint256 proofsLen = guardianProofs.length; - require(proofsLen >= threshold, Unauthorized()); - - uint256 validSignatures; - address[] memory seen = new address[](proofsLen); - - for (uint256 i; i < proofsLen; ++i) { - address guardian = _verifyGuardianSession( - guardianProofs[i].sessionId, - guardianProofs[i].sessionKey, - guardianProofs[i].ownerKey, - signedMessageHash, - guardianProofs[i].signature - ); - - bool duplicate; - for (uint256 j; j < validSignatures; ++j) { - if (seen[j] == guardian) { - duplicate = true; - break; - } - } - if (duplicate) continue; - - seen[validSignatures] = guardian; - ++validSignatures; - } - - return validSignatures >= threshold; - } - - /** - * @dev Verifies a TEE session signature, validates the session owner, and checks workload. - * @param sessionId The session id to verify against - * @param sessionKey The session's public key - * @param ownerKey The owner's public key (must be ES256K, 65 bytes) - * @param signedMessageHash The message hash that was signed - * @param signature The signature to verify - * @return guardian The guardian address derived from ownerKey - */ - function _verifyGuardianSession( - bytes32 sessionId, - PublicIdentity calldata sessionKey, - PublicIdentity calldata ownerKey, - bytes32 signedMessageHash, - bytes calldata signature - ) internal view returns (address guardian) { - require(ownerKey.typeId == ALGO_ID_ES256K, InvalidECDSAPubKey()); - require(ownerKey.key.length == _ECDSA_KEY_LENGTH, InvalidECDSAPubKey()); - - guardian = address(uint160(uint256(keccak256(ownerKey.key[1:])))); - require(_guardians.contains(guardian), Unauthorized()); - - bool valid = SESSION_REGISTRY.verifySessionSignature(sessionId, sessionKey, signedMessageHash, signature); - require(valid, InvalidSignature()); - - bytes32 ownerFingerprint = SESSION_REGISTRY.getSessionOwner(sessionId); - require(ownerFingerprint == LibKey.computeKeyFingerprint(ownerKey), InvalidECDSAPubKey()); - - CVMSession memory session = SESSION_REGISTRY.getSession(sessionId); - require(_allowedWorkloads[session.workloadId], WorkloadNotAllowed()); + return _validateSignatures(getGuardiansEnclaveAddresses(), enclaveSignatures, signedMessageHash); } /** @@ -341,6 +305,56 @@ contract GuardianModule is AccessManaged, IGuardianModule { return _guardians.values(); } + /** + * @inheritdoc IGuardianModule + */ + function rotateGuardianKey(uint256 blockNumber, bytes calldata pubKey, GuardianSessionProof calldata proof) + external + { + // The ownerKey is provided by the operator during TEE workload deployment (via atakit deploy --owner-private-key). + // The CVM agent binds the ownerKey to the session, so a valid session signature attests that the message originated from the operator. + require(proof.ownerKey.typeId == ALGO_ID_ES256K, InvalidECDSAPubKey()); + require(proof.ownerKey.key.length == _ECDSA_KEY_LENGTH, InvalidECDSAPubKey()); + + address guardian = address(uint160(uint256(keccak256(proof.ownerKey.key[1:])))); + + if (!_guardians.contains(guardian)) { + revert Unauthorized(); + } + + if (pubKey.length != _ECDSA_KEY_LENGTH) { + revert InvalidECDSAPubKey(); + } + + if ((block.number - blockNumber) > FRESHNESS_BLOCKS) { + revert StaleEvidence(); + } + + // Since rotateGuardianKey is called infrequently, blockNumber-based freshness is used for replay protection instead of a nonce. + bytes32 signedMessageHash = + keccak256(abi.encode("ROTATE_GUARDIAN_KEY", address(this), block.chainid, blockNumber, pubKey)); + bool isValid = SESSION_REGISTRY.verifySessionSignature( + proof.sessionId, proof.sessionKey, signedMessageHash, proof.signature + ); + if (!isValid) { + revert InvalidSignature(); + } + + bytes32 ownerFingerprint = SESSION_REGISTRY.getSessionOwner(proof.sessionId); + require(ownerFingerprint == LibKey.computeKeyFingerprint(proof.ownerKey), InvalidECDSAPubKey()); + + CVMSession memory session = SESSION_REGISTRY.getSession(proof.sessionId); + require(_allowedWorkloads[session.workloadId], WorkloadNotAllowed()); + + // pubKey[1:] means we need to strip the first byte '0x' if we want to get the correct address + address computedAddress = address(uint160(uint256(keccak256(pubKey[1:])))); + + _guardianEnclaves[guardian].enclaveAddress = computedAddress; + _guardianEnclaves[guardian].enclavePubKey = pubKey; + + emit RotatedGuardianKey(guardian, computedAddress, pubKey); + } + /** * @inheritdoc IGuardianModule */ @@ -348,6 +362,46 @@ contract GuardianModule is AccessManaged, IGuardianModule { return _ejectionThreshold; } + /** + * @inheritdoc IGuardianModule + */ + function getGuardiansEnclaveAddress(address guardian) external view returns (address) { + return _guardianEnclaves[guardian].enclaveAddress; + } + + /** + * @inheritdoc IGuardianModule + */ + function getGuardiansEnclaveAddresses() public view returns (address[] memory) { + uint256 guardiansLength = _guardians.length(); + address[] memory enclaveAddresses = new address[](guardiansLength); + + for (uint256 i; i < guardiansLength; ++i) { + // If the guardian doesn't have an enclave address, we use `0xdead` address + // The reason for this is that we use .tryRecover in signature verification, and a valid signature can be crafted to recover to address(0) + address enclaveAddress = _guardianEnclaves[_guardians.at(i)].enclaveAddress == address(0) + ? address(0x000000000000000000000000000000000000dEaD) + : _guardianEnclaves[_guardians.at(i)].enclaveAddress; + enclaveAddresses[i] = enclaveAddress; + } + + return enclaveAddresses; + } + + /** + * @inheritdoc IGuardianModule + */ + function getGuardiansEnclavePubkeys() external view returns (bytes[] memory) { + uint256 guardiansLength = _guardians.length(); + bytes[] memory enclavePubkeys = new bytes[](guardiansLength); + + for (uint256 i; i < guardiansLength; ++i) { + enclavePubkeys[i] = _guardianEnclaves[_guardians.at(i)].enclavePubKey; + } + + return enclavePubkeys; + } + /** * @inheritdoc IGuardianModule */ diff --git a/mainnet-contracts/src/PufferProtocol.sol b/mainnet-contracts/src/PufferProtocol.sol index 7779537a..d910547e 100644 --- a/mainnet-contracts/src/PufferProtocol.sol +++ b/mainnet-contracts/src/PufferProtocol.sol @@ -8,7 +8,7 @@ import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils import { PufferProtocolStorage } from "./PufferProtocolStorage.sol"; import { PufferModuleManager } from "./PufferModuleManager.sol"; import { IPufferOracleV2 } from "./interface/IPufferOracleV2.sol"; -import { IGuardianModule, GuardianSessionProof } from "./interface/IGuardianModule.sol"; +import { IGuardianModule } from "./interface/IGuardianModule.sol"; import { IBeaconDepositContract } from "./interface/IBeaconDepositContract.sol"; import { ValidatorKeyData } from "./struct/ValidatorKeyData.sol"; import { Validator } from "./struct/Validator.sol"; @@ -252,7 +252,7 @@ contract PufferProtocol is IPufferProtocol, AccessManagedUpgradeable, UUPSUpgrad * @dev Restricted to Puffer Paymaster */ function provisionNode( - GuardianSessionProof[] calldata guardianProofs, + bytes[] calldata guardianEnclaveSignatures, bytes calldata validatorSignature, bytes32 depositRootHash ) external restricted { @@ -275,7 +275,7 @@ contract PufferProtocol is IPufferProtocol, AccessManagedUpgradeable, UUPSUpgrad $: $, moduleName: moduleName, index: index, - guardianProofs: guardianProofs, + guardianEnclaveSignatures: guardianEnclaveSignatures, validatorSignature: validatorSignature }); @@ -612,15 +612,20 @@ contract PufferProtocol is IPufferProtocol, AccessManagedUpgradeable, UUPSUpgrad /** * @notice Returns necessary information to make Guardian's life easier */ - function getPayload(bytes32 moduleName, bool usingEnclave) external view returns (bytes memory, uint256, uint256) { + function getPayload(bytes32 moduleName, bool usingEnclave) + external + view + returns (bytes[] memory, bytes memory, uint256, uint256) + { ProtocolStorage storage $ = _getPufferProtocolStorage(); + bytes[] memory pubKeys = GUARDIAN_MODULE.getGuardiansEnclavePubkeys(); bytes memory withdrawalCredentials = getWithdrawalCredentials(address($.modules[moduleName])); uint256 threshold = GUARDIAN_MODULE.getThreshold(); uint256 validatorBond = usingEnclave ? _ENCLAVE_VALIDATOR_BOND : _NO_ENCLAVE_VALIDATOR_BOND; uint256 ethAmount = validatorBond + ($.minimumVtAmount * PUFFER_ORACLE.getValidatorTicketPrice()) / 1 ether; - return (withdrawalCredentials, threshold, ethAmount); + return (pubKeys, withdrawalCredentials, threshold, ethAmount); } /** @@ -765,7 +770,7 @@ contract PufferProtocol is IPufferProtocol, AccessManagedUpgradeable, UUPSUpgrad ProtocolStorage storage $, bytes32 moduleName, uint256 index, - GuardianSessionProof[] calldata guardianProofs, + bytes[] calldata guardianEnclaveSignatures, bytes calldata validatorSignature ) internal { bytes memory validatorPubKey = $.validators[moduleName][index].pubKey; @@ -782,7 +787,7 @@ contract PufferProtocol is IPufferProtocol, AccessManagedUpgradeable, UUPSUpgrad signature: validatorSignature, depositDataRoot: depositDataRoot, withdrawalCredentials: withdrawalCredentials, - guardianProofs: guardianProofs + guardianEnclaveSignatures: guardianEnclaveSignatures }); PufferModule module = $.modules[moduleName]; diff --git a/mainnet-contracts/src/interface/IGuardianModule.sol b/mainnet-contracts/src/interface/IGuardianModule.sol index 51f5dd7a..8350c4a9 100644 --- a/mainnet-contracts/src/interface/IGuardianModule.sol +++ b/mainnet-contracts/src/interface/IGuardianModule.sol @@ -4,6 +4,13 @@ pragma solidity >=0.8.0 <0.9.0; import { StoppedValidatorInfo } from "../struct/StoppedValidatorInfo.sol"; import { PublicIdentity } from "@automata-network/automata-tee-workload-measurement/types/Common.sol"; +/** + * @notice Proof of a guardian's session-based signature via SessionRegistry + * @param sessionId The session id to verify against + * @param sessionKey The session's public key + * @param ownerKey The owner's public key (identifies the guardian) + * @param signature The session signature over the message + */ struct GuardianSessionProof { bytes32 sessionId; PublicIdentity sessionKey; @@ -70,6 +77,15 @@ interface IGuardianModule { */ event GuardianRemoved(address guardian); + /** + * @notice Emitted when the guardian changes guardian enclave address + * @param guardian is the address outside of the enclave + * @param guardianEnclave is the enclave address + * @param pubKey is the public key + * @dev Signature "0x14720919b20fceff2a396c4973d37c6087e4619d40c8f4003d8e44ee127461a2" + */ + event RotatedGuardianKey(address guardian, address guardianEnclave, bytes pubKey); + /** * @notice Emitted when a workload allowance is changed * @param workloadId id of the workload @@ -78,6 +94,18 @@ interface IGuardianModule { */ event WorkloadAllowanceChanged(bytes32 workloadId, bool allowed); + /** + * @notice Thrown if the Evidence that we're trying to verify is stale + * Evidence should be submitted for the recent block < `FRESHNESS_BLOCKS` + * @dev Signature "0x5d4ad9a9" + */ + error StaleEvidence(); + + /** + * @notice Returns the enclave address registered to `guardian` + */ + function getGuardiansEnclaveAddress(address guardian) external view returns (address); + /** * @notice Returns the ejection threshold ETH value * @dev The ejection threshold is the minimum amount of ETH on the beacon chain required do the validation duties @@ -125,7 +153,7 @@ interface IGuardianModule { * @param signature The signature * @param withdrawalCredentials The withdrawal credentials * @param depositDataRoot The deposit data root - * @param guardianProofs The guardian session proofs + * @param guardianEnclaveSignatures The guardian enclave signatures */ function validateProvisionNode( uint256 pufferModuleIndex, @@ -133,7 +161,7 @@ interface IGuardianModule { bytes calldata signature, bytes calldata withdrawalCredentials, bytes32 depositDataRoot, - GuardianSessionProof[] calldata guardianProofs + bytes[] calldata guardianEnclaveSignatures ) external view; /** @@ -188,6 +216,17 @@ interface IGuardianModule { */ function setEjectionThreshold(uint256 newThreshold) external; + /** + * @dev Validates the signatures of the guardians' enclave signatures + * @param enclaveSignatures The array of enclave signatures + * @param signedMessageHash The hash of the signed message + * @return A boolean indicating whether the signatures are valid + */ + function validateGuardiansEnclaveSignatures(bytes[] calldata enclaveSignatures, bytes32 signedMessageHash) + external + view + returns (bool); + /** * @dev Validates the signatures of the guardians' EOAs. * @param eoaSignatures The array of EOAs' signatures. @@ -198,19 +237,27 @@ interface IGuardianModule { external view returns (bool); + /** + * @notice Rotates a guardian's enclave key using a SessionRegistry-based proof + * @dev The caller provides a session proof that attests the new enclave public key. + * The ownerKey in the proof must resolve to a registered guardian address. + * blockNumber-based freshness is used for replay protection. + * @param blockNumber The block number used for freshness verification + * @param pubKey The new uncompressed ECDSA enclave public key (65 bytes) + * @param proof The session proof containing sessionId, sessionKey, ownerKey, and signature + */ + function rotateGuardianKey(uint256 blockNumber, bytes calldata pubKey, GuardianSessionProof calldata proof) + external; /** - * @dev Validates an array of guardian session proofs against a message hash. - * Verifies each proof via SessionRegistry (including workload), prevents duplicate - * guardian counting, and requires at least `_threshold` unique valid guardian proofs. - * @param guardianProofs The array of guardian session proofs - * @param signedMessageHash The message hash that was signed - * @return A boolean indicating whether the session proofs are valid and meet the threshold requirement + * @notice Returns the guardians enclave addresses */ - function validateSessionProofs(GuardianSessionProof[] calldata guardianProofs, bytes32 signedMessageHash) - external - view - returns (bool); + function getGuardiansEnclaveAddresses() external view returns (address[] memory); + + /** + * @notice Returns the guardians enclave public keys + */ + function getGuardiansEnclavePubkeys() external view returns (bytes[] memory); /** * @notice Checks if an account is a guardian diff --git a/mainnet-contracts/src/interface/IPufferProtocol.sol b/mainnet-contracts/src/interface/IPufferProtocol.sol index 4d0fec0f..f6a87a69 100644 --- a/mainnet-contracts/src/interface/IPufferProtocol.sol +++ b/mainnet-contracts/src/interface/IPufferProtocol.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.0 <0.9.0; import { Validator } from "../struct/Validator.sol"; import { ValidatorKeyData } from "../struct/ValidatorKeyData.sol"; -import { IGuardianModule, GuardianSessionProof } from "../interface/IGuardianModule.sol"; +import { IGuardianModule } from "../interface/IGuardianModule.sol"; import { PufferModuleManager } from "../PufferModuleManager.sol"; import { PufferVaultV5 } from "../PufferVaultV5.sol"; import { IPufferOracleV2 } from "../interface/IPufferOracleV2.sol"; @@ -282,7 +282,7 @@ interface IPufferProtocol { * @dev You can check who is next for provisioning by calling `getNextValidatorToProvision` method */ function provisionNode( - GuardianSessionProof[] calldata guardianPro, + bytes[] calldata guardianEnclaveSignatures, bytes calldata validatorSignature, bytes32 depositRootHash ) external; diff --git a/mainnet-contracts/test/handlers/PufferProtocolHandler.sol b/mainnet-contracts/test/handlers/PufferProtocolHandler.sol index e85e1899..95892bcd 100644 --- a/mainnet-contracts/test/handlers/PufferProtocolHandler.sol +++ b/mainnet-contracts/test/handlers/PufferProtocolHandler.sol @@ -2,7 +2,6 @@ pragma solidity >=0.8.0 <0.9.0; import { IPufferProtocol } from "../../src/interface/IPufferProtocol.sol"; -import { GuardianSessionProof, PublicIdentity } from "../../src/interface/IGuardianModule.sol"; import { EnumerableMap } from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import { console } from "forge-std/console.sol"; @@ -27,7 +26,6 @@ import { PufferOracleV2 } from "../../src/PufferOracleV2.sol"; import { IWETH } from "../../src/interface/Other/IWETH.sol"; import { PufferVaultV5 } from "../../src/PufferVaultV5.sol"; import { PufferModule } from "../../src/PufferModule.sol"; -import { ALGO_ID_ES256K } from "@automata-network/automata-tee-workload-measurement/types/Constants.sol"; struct ProvisionedValidator { bytes32 moduleName; @@ -43,15 +41,9 @@ contract PufferProtocolHandler is Test { // Guardians are preset for the test environment, and these are the enclave secret keys uint256 guardian1SKEnclave = 81165043675487275545095207072241430673874640255053335052777448899322561824201; address guardian1Enclave = vm.addr(guardian1SKEnclave); - bytes guardian1EnclavePubkey = - hex"04caf1f9cd82a1284626d405d285250fd6c4f58c469fda05d7fd4f29318aae38e7ccc6f4eaced74d3e2aa3fc0576093860d3045263c4183d694a39911ee9031c73"; uint256 guardian2SKEnclave = 90480947395980135991870782913815514305328820213706480966227475230529794843518; address guardian2Enclave = vm.addr(guardian2SKEnclave); - bytes guardian2EnclavePubkey = - hex"04f050c3ce5d575600af388f41876e2962499a97bc8fcfa4a12adf7e4a486a3be9a1db0efd899c09723f83fe490e8215fd596a5f03c819e28a8b95f3cce6238613"; uint256 guardian3SKEnclave = 56094429399408807348734910221877888701411489680816282162734349635927251229227; - bytes guardian3EnclavePubkey = - hex"04a55b152177219971a93a64aafc2d61baeaf86526963caa260e71efa2b865527e0307d7bda85312dd6ff23bcc88f2bf228da6295239f72c31b686c48b7b69cdfd"; UnitTestHelper testhelper; address[] public actors; @@ -508,8 +500,8 @@ contract PufferProtocolHandler is Test { if (validatorData.status == Status.PENDING) { bytes memory sig = _getPubKey(validatorData.pubKeypart); - GuardianSessionProof[] memory guardianProofs = _getGuardianProofs(sig); - pufferProtocol.provisionNode(guardianProofs, mockValidatorSignature, bytes32(0)); + bytes[] memory signatures = _getGuardianSignatures(sig); + pufferProtocol.provisionNode(signatures, mockValidatorSignature, bytes32(0)); ghost_validators_validating.push(ProvisionedValidator({ moduleName: moduleName, idx: nextIdx })); @@ -603,12 +595,12 @@ contract PufferProtocolHandler is Test { } // Copied from PufferProtocol.t.sol - function _getGuardianProofs(bytes memory pubKey) internal view returns (GuardianSessionProof[] memory) { + function _getGuardianSignatures(bytes memory pubKey) internal view returns (bytes[] memory) { (bytes32 moduleName, uint256 pendingIdx) = pufferProtocol.getNextValidatorToProvision(); Validator memory validator = pufferProtocol.getValidatorInfo(moduleName, pendingIdx); // If there is no module return empty byte array if (validator.module == address(0)) { - return new GuardianSessionProof[](0); + return new bytes[](0); } bytes memory withdrawalCredentials = pufferProtocol.getWithdrawalCredentials(validator.module); @@ -624,10 +616,10 @@ contract PufferProtocolHandler is Test { }) ); - return _getGuardianEnclaveProofs(digest); + return _getGuardianEnclaveSignatures(digest); } - function _getGuardianEnclaveProofs(bytes32 digest) internal view returns (GuardianSessionProof[] memory) { + function _getGuardianEnclaveSignatures(bytes32 digest) internal view returns (bytes[] memory) { (uint8 v, bytes32 r, bytes32 s) = vm.sign(guardian1SKEnclave, digest); bytes memory signature1 = abi.encodePacked(r, s, v); // note the order here is different from line above. @@ -637,35 +629,12 @@ contract PufferProtocolHandler is Test { (v, r, s) = vm.sign(guardian3SKEnclave, digest); bytes memory signature3 = abi.encodePacked(r, s, v); // note the order here is different from line above. - // Pre-computed public keys from makeAddrAndKey() - bytes memory guardian1OwnerPubkey = - hex"04af497e622b580acc7e8d961bc7fa69aad88774ea39c838ff5411ac87746eb0d0b157c9e9b6f94d4b58313c7c59c975760b4c640e78d9e466e1a2255359d6e092"; - bytes memory guardian2OwnerPubkey = - hex"04169f04b8a0f6c552666fbccf9a73184bb0e2a1fbeb66ee56ca2c3271f9398803cad67262f0987f9ea085771868683b53944d421a081a73cce357275b47f3629f"; - bytes memory guardian3OwnerPubkey = - hex"04bcb747c6ce73688d800755ac8715198ca92e7d2f0a828e083e254078c8c652e64f15534685ba90ec89362c8c276df81c7e6a2db9f2f2620d7596d9962171d2fc"; - - GuardianSessionProof[] memory guardianProofs = new GuardianSessionProof[](3); - guardianProofs[0] = GuardianSessionProof({ - sessionId: keccak256("guardian1"), - sessionKey: PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian1EnclavePubkey }), - ownerKey: PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian1OwnerPubkey }), - signature: signature1 - }); - guardianProofs[1] = GuardianSessionProof({ - sessionId: keccak256("guardian2"), - sessionKey: PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian2EnclavePubkey }), - ownerKey: PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian2OwnerPubkey }), - signature: signature2 - }); - guardianProofs[2] = GuardianSessionProof({ - sessionId: keccak256("guardian3"), - sessionKey: PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian3EnclavePubkey }), - ownerKey: PublicIdentity({ typeId: ALGO_ID_ES256K, key: guardian3OwnerPubkey }), - signature: signature3 - }); - - return guardianProofs; + bytes[] memory guardianSignatures = new bytes[](3); + guardianSignatures[0] = signature1; + guardianSignatures[1] = signature2; + guardianSignatures[2] = signature3; + + return guardianSignatures; } function _getGuardianEOASignatures(bytes32 digest) internal returns (bytes[] memory) { diff --git a/mainnet-contracts/test/helpers/IntegrationTestHelper.sol b/mainnet-contracts/test/helpers/IntegrationTestHelper.sol index d48eb374..7ee2d094 100644 --- a/mainnet-contracts/test/helpers/IntegrationTestHelper.sol +++ b/mainnet-contracts/test/helpers/IntegrationTestHelper.sol @@ -29,6 +29,8 @@ contract IntegrationTestHelper is Test { address PAYMASTER = 0xeeE554b5b2bF5FBc9730Ce33c6dc92828DA01BeE; address SESSION_REGISTRY = 0xD1860020870ffEd23a644d0CD4CA9E7b3Ff53D6c; + uint256 public constant FRESHNESS_BLOCKS = 20; + // custom block number function deployContractsHoodi(uint256 blockNumber) public virtual { // see foundry.toml for the rpc urls @@ -52,7 +54,7 @@ contract IntegrationTestHelper is Test { function _deployAndLabel(address[] memory guardians, uint256 threshold) internal { // Deploy everything with one script (PufferProtocolDeployment memory pufferDeployment,) = - new DeployEverything().run(SESSION_REGISTRY, guardians, threshold, PAYMASTER); + new DeployEverything().run(SESSION_REGISTRY, guardians, threshold, PAYMASTER, FRESHNESS_BLOCKS); pufferProtocol = PufferProtocol(payable(pufferDeployment.pufferProtocol)); vm.label(address(pufferProtocol), "PufferProtocol"); diff --git a/mainnet-contracts/test/helpers/UnitTestHelper.sol b/mainnet-contracts/test/helpers/UnitTestHelper.sol index 039560d4..c72d0479 100644 --- a/mainnet-contracts/test/helpers/UnitTestHelper.sol +++ b/mainnet-contracts/test/helpers/UnitTestHelper.sol @@ -70,6 +70,8 @@ contract UnitTestHelper is Test, BaseScript { address public constant ADDRESS_ONE = address(1); address public constant ADDRESS_CHEATS = 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D; + uint256 public constant FRESHNESS_BLOCKS = 20; + // Addresses that are supposed to be skipped when fuzzing mapping(address fuzzedAddress => bool isFuzzed) internal fuzzedAddressMapping; @@ -240,7 +242,7 @@ contract UnitTestHelper is Test, BaseScript { BridgingDeployment memory bridgingDeployment; (pufferDeployment, bridgingDeployment) = - new DeployEverything().run(address(sessionRegistryMock), guardians, 1, PAYMASTER); + new DeployEverything().run(address(sessionRegistryMock), guardians, 1, PAYMASTER, FRESHNESS_BLOCKS); pufferProtocol = PufferProtocol(payable(pufferDeployment.pufferProtocol)); accessManager = AccessManager(pufferDeployment.accessManager); @@ -300,6 +302,8 @@ contract UnitTestHelper is Test, BaseScript { sessionRegistryMock.setSessionOwner( guardian3SessionId, LibKey.computeKeyFingerprint(guardian3OwnerPublicIdentity) ); + + // TODO Add Rotate guardians } function _upgradePufferVaultToMainnet() internal { diff --git a/mainnet-contracts/test/unit/PufferProtocol.t.sol b/mainnet-contracts/test/unit/PufferProtocol.t.sol index 0de28a05..bff105a3 100644 --- a/mainnet-contracts/test/unit/PufferProtocol.t.sol +++ b/mainnet-contracts/test/unit/PufferProtocol.t.sol @@ -16,8 +16,6 @@ import { LibGuardianMessages } from "../../src/LibGuardianMessages.sol"; import { Permit } from "../../src/structs/Permit.sol"; import { ModuleLimit } from "../../src/struct/ProtocolStorage.sol"; import { StoppedValidatorInfo } from "../../src/struct/StoppedValidatorInfo.sol"; -import { GuardianSessionProof, PublicIdentity, IGuardianModule } from "../../src/interface/IGuardianModule.sol"; -import { ALGO_ID_ES256K } from "@automata-network/automata-tee-workload-measurement/types/Constants.sol"; contract PufferProtocolTest is UnitTestHelper { using ECDSA for bytes32; @@ -76,17 +74,6 @@ contract PufferProtocolTest is UnitTestHelper { NoRestakingModule = pufferProtocol.getModuleAddress(PUFFER_MODULE_0); // Fund no restaking module with 200 ETH vm.deal(NoRestakingModule, 200 ether); - - // Set allowed workload in GuardianModule and sessionRegistry mock - bytes32 workload1 = keccak256("workload1"); - bytes32 workload2 = keccak256("workload2"); - bytes32 workload3 = keccak256("workload3"); - guardianModule.setAllowedWorkload(workload1, true); - guardianModule.setAllowedWorkload(workload2, true); - guardianModule.setAllowedWorkload(workload3, true); - sessionRegistryMock.setSessionWorkload(guardian1SessionId, workload1); - sessionRegistryMock.setSessionWorkload(guardian2SessionId, workload2); - sessionRegistryMock.setSessionWorkload(guardian3SessionId, workload3); } // Setup @@ -145,11 +132,11 @@ contract PufferProtocolTest is UnitTestHelper { assertEq(moduleName, PUFFER_MODULE_0, "module"); assertEq(idx, 1, "idx should be 1"); - GuardianSessionProof[] memory guardianProofs = _getGuardianProofs(_getPubKey(bytes32("bob"))); + bytes[] memory signatures = _getGuardianSignatures(_getPubKey(bytes32("bob"))); vm.expectEmit(true, true, true, true); emit SuccessfullyProvisioned(_getPubKey(bytes32("bob")), 1, PUFFER_MODULE_0); - pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(signatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); moduleSelectionIndex = pufferProtocol.getModuleSelectIndex(); assertEq(moduleSelectionIndex, 1, "module idx changed"); } @@ -299,17 +286,28 @@ contract PufferProtocolTest is UnitTestHelper { ); } + function test_get_payload() public view { + (bytes[] memory guardianPubKeys,, uint256 threshold,) = pufferProtocol.getPayload(PUFFER_MODULE_0, false); + + assertEq(guardianPubKeys[0], guardian1EnclavePubKey, "guardian1"); + assertEq(guardianPubKeys[1], guardian2EnclavePubKey, "guardian2"); + assertEq(guardianPubKeys[2], guardian3EnclavePubKey, "guardian3"); + + assertEq(guardianPubKeys.length, 3, "pubkeys len"); + assertEq(threshold, 1, "threshold"); + } + // Try to provision a validator when there is nothing to provision function test_provision_reverts() public { (, uint256 idx) = pufferProtocol.getNextValidatorToProvision(); assertEq(type(uint256).max, idx, "module"); // Invalid signatures - GuardianSessionProof[] memory guardianProofs = - _getGuardianProofs(hex"0000000000000000000000000000000000000000000000000000"); + bytes[] memory signatures = + _getGuardianSignatures(hex"0000000000000000000000000000000000000000000000000000000000000000"); vm.expectRevert(); // panic - pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(signatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); } // If the deposit root is not bytes(0), it must match match the one returned from the beacon contract @@ -317,13 +315,13 @@ contract PufferProtocolTest is UnitTestHelper { _registerValidatorKey(zeroPubKeyPart, PUFFER_MODULE_0); bytes memory validatorSignature = _validatorSignature(); - GuardianSessionProof[] memory guardianProofs = _getGuardianProofs(_getPubKey(zeroPubKeyPart)); + bytes[] memory guardianSignatures = _getGuardianSignatures(_getPubKey(zeroPubKeyPart)); vm.expectRevert(IPufferProtocol.InvalidDepositRootHash.selector); - pufferProtocol.provisionNode(guardianProofs, validatorSignature, bytes32("badDepositRoot")); // "depositRoot" is hardcoded in the mock + pufferProtocol.provisionNode(guardianSignatures, validatorSignature, bytes32("badDepositRoot")); // "depositRoot" is hardcoded in the mock // now it works - pufferProtocol.provisionNode(guardianProofs, validatorSignature, DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(guardianSignatures, validatorSignature, DEFAULT_DEPOSIT_ROOT); } function test_register_multiple_validators_and_skipProvisioning(bytes32 alicePubKeyPart, bytes32 bobPubKeyPart) @@ -360,19 +358,19 @@ contract PufferProtocolTest is UnitTestHelper { assertEq(pufferProtocol.getPendingValidatorIndex(PUFFER_MODULE_0), 5, "next pending validator index"); - GuardianSessionProof[] memory guardianProofs = _getGuardianProofs(zeroPubKey); + bytes[] memory signatures = _getGuardianSignatures(zeroPubKey); // 1. provision zero key vm.expectEmit(true, true, true, true); emit SuccessfullyProvisioned(zeroPubKey, 0, PUFFER_MODULE_0); - pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(signatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); - GuardianSessionProof[] memory bobGuardianProofs = _getGuardianProofs(bobPubKey); + bytes[] memory bobSignatures = _getGuardianSignatures(bobPubKey); // Provision Bob that is not zero pubKey vm.expectEmit(true, true, true, true); emit SuccessfullyProvisioned(bobPubKey, 1, PUFFER_MODULE_0); - pufferProtocol.provisionNode(bobGuardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(bobSignatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); Validator memory bobValidator = pufferProtocol.getValidatorInfo(PUFFER_MODULE_0, 1); @@ -380,10 +378,10 @@ contract PufferProtocolTest is UnitTestHelper { pufferProtocol.skipProvisioning(PUFFER_MODULE_0, _getGuardianSignaturesForSkipping()); - guardianProofs = _getGuardianProofs(zeroPubKey); + signatures = _getGuardianSignatures(zeroPubKey); emit SuccessfullyProvisioned(zeroPubKey, 3, PUFFER_MODULE_0); - pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(signatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); // Get validators Validator[] memory registeredValidators = pufferProtocol.getValidators(PUFFER_MODULE_0); @@ -429,12 +427,12 @@ contract PufferProtocolTest is UnitTestHelper { assertTrue(nextModule == PUFFER_MODULE_0, "module selection"); assertTrue(nextId == 0, "module selection"); - GuardianSessionProof[] memory guardianProofs = _getGuardianProofs(_getPubKey(bytes32("bob"))); + bytes[] memory signatures = _getGuardianSignatures(_getPubKey(bytes32("bob"))); // Provision Bob that is not zero pubKey vm.expectEmit(true, true, true, true); emit SuccessfullyProvisioned(_getPubKey(bytes32("bob")), 0, PUFFER_MODULE_0); - pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(signatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); (nextModule, nextId) = pufferProtocol.getNextValidatorToProvision(); @@ -442,11 +440,11 @@ contract PufferProtocolTest is UnitTestHelper { // Id is zero, because that is the first in this queue assertTrue(nextId == 0, "module id"); - guardianProofs = _getGuardianProofs(_getPubKey(bytes32("benjamin"))); + signatures = _getGuardianSignatures(_getPubKey(bytes32("benjamin"))); vm.expectEmit(true, true, true, true); emit SuccessfullyProvisioned(_getPubKey(bytes32("benjamin")), 0, EIGEN_DA); - pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(signatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); (nextModule, nextId) = pufferProtocol.getNextValidatorToProvision(); @@ -466,23 +464,23 @@ contract PufferProtocolTest is UnitTestHelper { assertTrue(nextId == 1, "module id"); // Provisioning of rocky should fail, because jason is next in line - guardianProofs = _getGuardianProofs(_getPubKey(bytes32("rocky"))); - vm.expectRevert(IGuardianModule.InvalidSignature.selector); - pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + signatures = _getGuardianSignatures(_getPubKey(bytes32("rocky"))); + vm.expectRevert(Unauthorized.selector); + pufferProtocol.provisionNode(signatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); - guardianProofs = _getGuardianProofs(_getPubKey(bytes32("jason"))); + signatures = _getGuardianSignatures(_getPubKey(bytes32("jason"))); // Provision Jason - pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(signatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); (nextModule, nextId) = pufferProtocol.getNextValidatorToProvision(); - guardianProofs = _getGuardianProofs(_getPubKey(bytes32("rocky"))); + signatures = _getGuardianSignatures(_getPubKey(bytes32("rocky"))); // Rocky is now in line assertTrue(nextModule == CRAZY_GAINS, "module selection"); assertTrue(nextId == 0, "module id"); - pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(signatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); (nextModule, nextId) = pufferProtocol.getNextValidatorToProvision(); @@ -493,11 +491,11 @@ contract PufferProtocolTest is UnitTestHelper { pufferProtocol.getNextValidatorToBeProvisionedIndex(PUFFER_MODULE_0), 1, "next idx for no restaking module" ); - guardianProofs = _getGuardianProofs(_getPubKey(bytes32("alice"))); + signatures = _getGuardianSignatures(_getPubKey(bytes32("alice"))); vm.expectEmit(true, true, true, true); emit SuccessfullyProvisioned(_getPubKey(bytes32("alice")), 1, PUFFER_MODULE_0); - pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(signatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); } function test_create_puffer_module() public { @@ -757,18 +755,18 @@ contract PufferProtocolTest is UnitTestHelper { vm.deal(address(pufferVault), 100 ether); _registerValidatorKey(bytes32("alice"), PUFFER_MODULE_0); - GuardianSessionProof[] memory guardianProofs = _getGuardianProofs(_getPubKey(bytes32("alice"))); + bytes[] memory guardianSignatures = _getGuardianSignatures(_getPubKey(bytes32("alice"))); // Register and provision Alice // Alice may be an active validator or it can be exited, doesn't matter - pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + pufferProtocol.provisionNode(guardianSignatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); // Register another validator with using the same data _registerValidatorKey(bytes32("alice"), PUFFER_MODULE_0); // Try to provision it with the original message (replay attack) // It should revert - vm.expectRevert(IGuardianModule.InvalidSignature.selector); - pufferProtocol.provisionNode(guardianProofs, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); + vm.expectRevert(Unauthorized.selector); + pufferProtocol.provisionNode(guardianSignatures, _validatorSignature(), DEFAULT_DEPOSIT_ROOT); } function test_validator_limit_per_module() external { @@ -818,7 +816,7 @@ contract PufferProtocolTest is UnitTestHelper { vm.warp(startTimestamp); pufferProtocol.provisionNode( - _getGuardianProofs(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT + _getGuardianSignatures(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT ); // Didn't claim the bond yet @@ -1469,7 +1467,7 @@ contract PufferProtocolTest is UnitTestHelper { uint256 startTimestamp = 1707411226; vm.warp(startTimestamp); pufferProtocol.provisionNode( - _getGuardianProofs(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT + _getGuardianSignatures(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT ); // Give funds to modules @@ -1523,7 +1521,7 @@ contract PufferProtocolTest is UnitTestHelper { uint256 startTimestamp = 1707411226; vm.warp(startTimestamp); pufferProtocol.provisionNode( - _getGuardianProofs(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT + _getGuardianSignatures(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT ); vm.deal(NoRestakingModule, 200 ether); @@ -1575,7 +1573,7 @@ contract PufferProtocolTest is UnitTestHelper { uint256 startTimestamp = 1707411226; vm.warp(startTimestamp); pufferProtocol.provisionNode( - _getGuardianProofs(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT + _getGuardianSignatures(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT ); vm.deal(NoRestakingModule, 200 ether); @@ -1635,7 +1633,7 @@ contract PufferProtocolTest is UnitTestHelper { uint256 startTimestamp = 1707411226; vm.warp(startTimestamp); pufferProtocol.provisionNode( - _getGuardianProofs(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT + _getGuardianSignatures(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT ); vm.deal(NoRestakingModule, 200 ether); @@ -1687,7 +1685,7 @@ contract PufferProtocolTest is UnitTestHelper { uint256 startTimestamp = 1707411226; vm.warp(startTimestamp); pufferProtocol.provisionNode( - _getGuardianProofs(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT + _getGuardianSignatures(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT ); vm.deal(NoRestakingModule, 200 ether); @@ -1730,7 +1728,7 @@ contract PufferProtocolTest is UnitTestHelper { vm.stopPrank(); pufferProtocol.provisionNode( - _getGuardianProofs(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT + _getGuardianSignatures(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT ); // Alice exited after 1 day @@ -1760,7 +1758,7 @@ contract PufferProtocolTest is UnitTestHelper { vm.stopPrank(); pufferProtocol.provisionNode( - _getGuardianProofs(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT + _getGuardianSignatures(_getPubKey(bytes32("alice"))), _validatorSignature(), DEFAULT_DEPOSIT_ROOT ); vm.startPrank(DAO); @@ -1856,60 +1854,12 @@ contract PufferProtocolTest is UnitTestHelper { assertEq(validatorTicket.balanceOf(bob), 50 ether, "bob got the VT"); } - function test_failing_verification() public { - vm.deal(alice, 10 ether); - - vm.startPrank(alice); - _registerValidatorKey(bytes32("alice"), PUFFER_MODULE_0); - vm.stopPrank(); - - // No workload allowed - guardianModule.setAllowedWorkload(keccak256("workload1"), false); - - GuardianSessionProof[] memory proofs = _getGuardianProofs(_getPubKey(bytes32("alice"))); - bytes memory signature = _validatorSignature(); - - vm.expectRevert(IGuardianModule.WorkloadNotAllowed.selector); - pufferProtocol.provisionNode(proofs, signature, DEFAULT_DEPOSIT_ROOT); - - guardianModule.setAllowedWorkload(keccak256("workload1"), true); - - // Invalid type id - proofs[0].ownerKey.typeId = 0; - - vm.expectRevert(IGuardianModule.InvalidECDSAPubKey.selector); - pufferProtocol.provisionNode(proofs, signature, DEFAULT_DEPOSIT_ROOT); - - proofs[0].ownerKey.typeId = ALGO_ID_ES256K; - - // Invalid key length - bytes memory realOwnerKey = proofs[0].ownerKey.key; - proofs[0].ownerKey.key = hex"04caf1"; - - vm.expectRevert(IGuardianModule.InvalidECDSAPubKey.selector); - pufferProtocol.provisionNode(proofs, signature, DEFAULT_DEPOSIT_ROOT); - - proofs[0].ownerKey.key = realOwnerKey; - - // Invalid ownerFingerprint - sessionRegistryMock.setSessionOwner(guardian1SessionId, bytes32("invalidFingerprint")); - - vm.expectRevert(IGuardianModule.InvalidECDSAPubKey.selector); - pufferProtocol.provisionNode(proofs, signature, DEFAULT_DEPOSIT_ROOT); - - // InvalidSignature - - proofs[0].signature = hex"beef"; - vm.expectRevert(IGuardianModule.InvalidSignature.selector); - pufferProtocol.provisionNode(proofs, signature, DEFAULT_DEPOSIT_ROOT); - } - - function _getGuardianProofs(bytes memory pubKey) internal view returns (GuardianSessionProof[] memory) { + function _getGuardianSignatures(bytes memory pubKey) internal view returns (bytes[] memory) { (bytes32 moduleName, uint256 pendingIdx) = pufferProtocol.getNextValidatorToProvision(); Validator memory validator = pufferProtocol.getValidatorInfo(moduleName, pendingIdx); // If there is no module return empty byte array if (validator.module == address(0)) { - return new GuardianSessionProof[](0); + return new bytes[](0); } bytes memory withdrawalCredentials = pufferProtocol.getWithdrawalCredentials(validator.module); @@ -1929,31 +1879,18 @@ contract PufferProtocolTest is UnitTestHelper { bytes memory signature1 = abi.encodePacked(r, s, v); // note the order here is different from line above. (v, r, s) = vm.sign(guardian2SKEnclave, digest); + (v, r, s) = vm.sign(guardian3SKEnclave, digest); bytes memory signature2 = abi.encodePacked(r, s, v); // note the order here is different from line above. (v, r, s) = vm.sign(guardian3SKEnclave, digest); bytes memory signature3 = abi.encodePacked(r, s, v); // note the order here is different from line above. - GuardianSessionProof[] memory guardianProofs = new GuardianSessionProof[](3); - guardianProofs[0] = GuardianSessionProof({ - sessionId: guardian1SessionId, - sessionKey: guardian1SessionPublicIdentity, - ownerKey: guardian1OwnerPublicIdentity, - signature: signature1 - }); - guardianProofs[1] = GuardianSessionProof({ - sessionId: guardian2SessionId, - sessionKey: guardian2SessionPublicIdentity, - ownerKey: guardian2OwnerPublicIdentity, - signature: signature2 - }); - guardianProofs[2] = GuardianSessionProof({ - sessionId: guardian3SessionId, - sessionKey: guardian3SessionPublicIdentity, - ownerKey: guardian3OwnerPublicIdentity, - signature: signature3 - }); - return guardianProofs; + bytes[] memory guardianSignatures = new bytes[](3); + guardianSignatures[0] = signature1; + guardianSignatures[1] = signature2; + guardianSignatures[2] = signature3; + + return guardianSignatures; } function _getGuardianSignaturesForSkipping() internal view returns (bytes[] memory) { @@ -2097,7 +2034,7 @@ contract PufferProtocolTest is UnitTestHelper { vm.stopPrank(); pufferProtocol.provisionNode( - _getGuardianProofs(_getPubKey(pubKeyPart)), _validatorSignature(), DEFAULT_DEPOSIT_ROOT + _getGuardianSignatures(_getPubKey(pubKeyPart)), _validatorSignature(), DEFAULT_DEPOSIT_ROOT ); } From 271ed696e9979bd3dc2bc39dbcbb41710d1416c4 Mon Sep 17 00:00:00 2001 From: Eladio Date: Mon, 2 Mar 2026 16:59:25 +0100 Subject: [PATCH 34/51] Fixed failing tests --- .../test/helpers/UnitTestHelper.sol | 88 ++++++++++++++++++- 1 file changed, 86 insertions(+), 2 deletions(-) diff --git a/mainnet-contracts/test/helpers/UnitTestHelper.sol b/mainnet-contracts/test/helpers/UnitTestHelper.sol index c72d0479..dee766d8 100644 --- a/mainnet-contracts/test/helpers/UnitTestHelper.sol +++ b/mainnet-contracts/test/helpers/UnitTestHelper.sol @@ -9,7 +9,7 @@ import { PufferProtocol } from "../../src/PufferProtocol.sol"; import { PufferModuleManager } from "../../src/PufferModuleManager.sol"; import { AVSContractsRegistry } from "../../src/AVSContractsRegistry.sol"; import { RestakingOperatorController } from "../../src/RestakingOperatorController.sol"; -import { IGuardianModule, PublicIdentity } from "../../src/interface/IGuardianModule.sol"; +import { IGuardianModule, GuardianSessionProof, PublicIdentity } from "../../src/interface/IGuardianModule.sol"; import { UpgradeableBeacon } from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; import { DeployEverything } from "../../script/DeployEverything.s.sol"; import { PufferProtocolDeployment, BridgingDeployment } from "../../script/DeploymentStructs.sol"; @@ -116,6 +116,10 @@ contract UnitTestHelper is Test, BaseScript { bytes32 public guardian2SessionId; bytes32 public guardian3SessionId; + GuardianSessionProof guardian1SessionProof; + GuardianSessionProof guardian2SessionProof; + GuardianSessionProof guardian3SessionProof; + SessionRegistryMock public sessionRegistryMock; // TDX attestation test data @@ -293,6 +297,38 @@ contract UnitTestHelper is Test, BaseScript { guardian2SessionId = keccak256("guardian2"); guardian3SessionId = keccak256("guardian3"); + bytes32 signedMessageHash1 = keccak256(abi.encode("ROTATE_GUARDIAN_KEY", address(guardianModule), block.chainid, 0, guardian1EnclavePubKey)); + bytes32 signedMessageHash2 = keccak256(abi.encode("ROTATE_GUARDIAN_KEY", address(guardianModule), block.chainid, 0, guardian2EnclavePubKey)); + bytes32 signedMessageHash3 = keccak256(abi.encode("ROTATE_GUARDIAN_KEY", address(guardianModule), block.chainid, 0, guardian3EnclavePubKey)); + + (uint8 v, bytes32 r, bytes32 s) = vm.sign(guardian1SKEnclave, signedMessageHash1); + bytes memory signature1 = abi.encodePacked(r, s, v); // note the order here is different from line above. + + (v, r, s) = vm.sign(guardian2SKEnclave, signedMessageHash2); + bytes memory signature2 = abi.encodePacked(r, s, v); // note the order here is different from line above. + + (v, r, s) = vm.sign(guardian3SKEnclave, signedMessageHash3); + bytes memory signature3 = abi.encodePacked(r, s, v); // note the order here is different from line above. + + guardian1SessionProof = GuardianSessionProof({ + sessionId: guardian1SessionId, + sessionKey: guardian1SessionPublicIdentity, + ownerKey: guardian1OwnerPublicIdentity, + signature: signature1 + }); + guardian2SessionProof = GuardianSessionProof({ + sessionId: guardian2SessionId, + sessionKey: guardian2SessionPublicIdentity, + ownerKey: guardian2OwnerPublicIdentity, + signature: signature2 + }); + guardian3SessionProof = GuardianSessionProof({ + sessionId: guardian3SessionId, + sessionKey: guardian3SessionPublicIdentity, + ownerKey: guardian3OwnerPublicIdentity, + signature: signature3 + }); + sessionRegistryMock.setSessionOwner( guardian1SessionId, LibKey.computeKeyFingerprint(guardian1OwnerPublicIdentity) ); @@ -303,7 +339,55 @@ contract UnitTestHelper is Test, BaseScript { guardian3SessionId, LibKey.computeKeyFingerprint(guardian3OwnerPublicIdentity) ); - // TODO Add Rotate guardians + bytes32 workloadId = keccak256("workload"); + vm.startPrank(DAO); + guardianModule.setAllowedWorkload(workloadId, true); + vm.stopPrank(); + + sessionRegistryMock.setSessionWorkload(guardian1SessionId, workloadId); + sessionRegistryMock.setSessionWorkload(guardian2SessionId, workloadId); + sessionRegistryMock.setSessionWorkload(guardian3SessionId, workloadId); + + // Register enclave keys for guardians + vm.startPrank(guardians[0]); + vm.expectEmit(true, true, true, true); + emit IGuardianModule.RotatedGuardianKey(guardians[0], guardian1Enclave, guardian1EnclavePubKey); + guardianModule.rotateGuardianKey( + 0, + guardian1EnclavePubKey, + guardian1SessionProof + ); + vm.stopPrank(); + + vm.startPrank(guardians[1]); + vm.expectEmit(true, true, true, true); + emit IGuardianModule.RotatedGuardianKey(guardians[1], guardian2Enclave, guardian2EnclavePubKey); + guardianModule.rotateGuardianKey( + 0, + guardian2EnclavePubKey, + guardian2SessionProof + ); + vm.stopPrank(); + + vm.startPrank(guardians[2]); + vm.expectEmit(true, true, true, true); + emit IGuardianModule.RotatedGuardianKey(guardians[2], guardian3Enclave, guardian3EnclavePubKey); + guardianModule.rotateGuardianKey( + 0, + guardian3EnclavePubKey, + guardian3SessionProof + ); + vm.stopPrank(); + + assertEq(guardianModule.getGuardiansEnclaveAddress(guardians[0]), guardian1Enclave, "bad enclave address1"); + assertEq(guardianModule.getGuardiansEnclaveAddress(guardians[1]), guardian2Enclave, "bad enclave address2"); + assertEq(guardianModule.getGuardiansEnclaveAddress(guardians[2]), guardian3Enclave, "bad enclave address3"); + + bytes[] memory pubKeys = guardianModule.getGuardiansEnclavePubkeys(); + assertEq(pubKeys[0], guardian1EnclavePubKey, "guardian1 pub key"); + assertEq(pubKeys[1], guardian2EnclavePubKey, "guardian2 pub key"); + assertEq(pubKeys[2], guardian3EnclavePubKey, "guardian3 pub key"); + } function _upgradePufferVaultToMainnet() internal { From 62178552872e809b232084c13803165760ee9ef9 Mon Sep 17 00:00:00 2001 From: Eladio Date: Tue, 3 Mar 2026 14:15:33 +0100 Subject: [PATCH 35/51] Implemented tests in GuardianModule --- mainnet-contracts/src/GuardianModule.sol | 2 +- .../test/helpers/UnitTestHelper.sol | 37 +-- .../test/unit/GuardianModule.t.sol | 215 +++++++++++++++++- 3 files changed, 227 insertions(+), 27 deletions(-) diff --git a/mainnet-contracts/src/GuardianModule.sol b/mainnet-contracts/src/GuardianModule.sol index 95527cb7..7025b44c 100644 --- a/mainnet-contracts/src/GuardianModule.sol +++ b/mainnet-contracts/src/GuardianModule.sol @@ -57,7 +57,7 @@ contract GuardianModule is AccessManaged, IGuardianModule { EnumerableSet.AddressSet private _guardians; /** - * @dev Threshold for the guardians + * @dev Threshold for the guardians. If the number of signatures/proofs is below this threshold, the action will not be authorized */ uint256 internal _threshold; diff --git a/mainnet-contracts/test/helpers/UnitTestHelper.sol b/mainnet-contracts/test/helpers/UnitTestHelper.sol index dee766d8..fd4a219e 100644 --- a/mainnet-contracts/test/helpers/UnitTestHelper.sol +++ b/mainnet-contracts/test/helpers/UnitTestHelper.sol @@ -297,9 +297,15 @@ contract UnitTestHelper is Test, BaseScript { guardian2SessionId = keccak256("guardian2"); guardian3SessionId = keccak256("guardian3"); - bytes32 signedMessageHash1 = keccak256(abi.encode("ROTATE_GUARDIAN_KEY", address(guardianModule), block.chainid, 0, guardian1EnclavePubKey)); - bytes32 signedMessageHash2 = keccak256(abi.encode("ROTATE_GUARDIAN_KEY", address(guardianModule), block.chainid, 0, guardian2EnclavePubKey)); - bytes32 signedMessageHash3 = keccak256(abi.encode("ROTATE_GUARDIAN_KEY", address(guardianModule), block.chainid, 0, guardian3EnclavePubKey)); + bytes32 signedMessageHash1 = keccak256( + abi.encode("ROTATE_GUARDIAN_KEY", address(guardianModule), block.chainid, 0, guardian1EnclavePubKey) + ); + bytes32 signedMessageHash2 = keccak256( + abi.encode("ROTATE_GUARDIAN_KEY", address(guardianModule), block.chainid, 0, guardian2EnclavePubKey) + ); + bytes32 signedMessageHash3 = keccak256( + abi.encode("ROTATE_GUARDIAN_KEY", address(guardianModule), block.chainid, 0, guardian3EnclavePubKey) + ); (uint8 v, bytes32 r, bytes32 s) = vm.sign(guardian1SKEnclave, signedMessageHash1); bytes memory signature1 = abi.encodePacked(r, s, v); // note the order here is different from line above. @@ -349,35 +355,17 @@ contract UnitTestHelper is Test, BaseScript { sessionRegistryMock.setSessionWorkload(guardian3SessionId, workloadId); // Register enclave keys for guardians - vm.startPrank(guardians[0]); vm.expectEmit(true, true, true, true); emit IGuardianModule.RotatedGuardianKey(guardians[0], guardian1Enclave, guardian1EnclavePubKey); - guardianModule.rotateGuardianKey( - 0, - guardian1EnclavePubKey, - guardian1SessionProof - ); - vm.stopPrank(); + guardianModule.rotateGuardianKey(0, guardian1EnclavePubKey, guardian1SessionProof); - vm.startPrank(guardians[1]); vm.expectEmit(true, true, true, true); emit IGuardianModule.RotatedGuardianKey(guardians[1], guardian2Enclave, guardian2EnclavePubKey); - guardianModule.rotateGuardianKey( - 0, - guardian2EnclavePubKey, - guardian2SessionProof - ); - vm.stopPrank(); + guardianModule.rotateGuardianKey(0, guardian2EnclavePubKey, guardian2SessionProof); - vm.startPrank(guardians[2]); vm.expectEmit(true, true, true, true); emit IGuardianModule.RotatedGuardianKey(guardians[2], guardian3Enclave, guardian3EnclavePubKey); - guardianModule.rotateGuardianKey( - 0, - guardian3EnclavePubKey, - guardian3SessionProof - ); - vm.stopPrank(); + guardianModule.rotateGuardianKey(0, guardian3EnclavePubKey, guardian3SessionProof); assertEq(guardianModule.getGuardiansEnclaveAddress(guardians[0]), guardian1Enclave, "bad enclave address1"); assertEq(guardianModule.getGuardiansEnclaveAddress(guardians[1]), guardian2Enclave, "bad enclave address2"); @@ -387,7 +375,6 @@ contract UnitTestHelper is Test, BaseScript { assertEq(pubKeys[0], guardian1EnclavePubKey, "guardian1 pub key"); assertEq(pubKeys[1], guardian2EnclavePubKey, "guardian2 pub key"); assertEq(pubKeys[2], guardian3EnclavePubKey, "guardian3 pub key"); - } function _upgradePufferVaultToMainnet() internal { diff --git a/mainnet-contracts/test/unit/GuardianModule.t.sol b/mainnet-contracts/test/unit/GuardianModule.t.sol index 95d5658d..9e9bdbbd 100644 --- a/mainnet-contracts/test/unit/GuardianModule.t.sol +++ b/mainnet-contracts/test/unit/GuardianModule.t.sol @@ -2,15 +2,41 @@ pragma solidity >=0.8.0 <0.9.0; import { UnitTestHelper } from "../helpers/UnitTestHelper.sol"; -import { IGuardianModule } from "../../src/interface/IGuardianModule.sol"; +import { IGuardianModule, PublicIdentity, GuardianSessionProof } from "../../src/interface/IGuardianModule.sol"; import { Unauthorized } from "../../src/Errors.sol"; import { SessionRegistryMock } from "../mocks/SessionRegistryMock.sol"; +import { ALGO_ID_ES256K } from "@automata-network/automata-tee-workload-measurement/types/Constants.sol"; +import { LibKey } from "@automata-network/automata-tee-workload-measurement/lib/LibKey.sol"; contract GuardianModuleTest is UnitTestHelper { + uint256 public newSKEnclave; + bytes public newEnclavePubKey; + + uint256 public newSKGuardian; + address public newGuardian; + bytes public newGuardianPubKey; + + PublicIdentity public newGuardianOwnerPublicIdentity; + PublicIdentity public newGuardianSessionPublicIdentity; + + bytes32 public newGuardianSessionId = keccak256("newGuardianSessionId"); + function setUp() public override { // Just call the parent setUp() super.setUp(); _skipDefaultFuzzAddresses(); + + newSKEnclave = 40280701971156975094650330025087207427871411154031414620449944599045365691365; + newEnclavePubKey = + hex"04f6a0b4231ab4442dff42aeeb7a0f761d0591cd10f6ef793b545a78130955e485ce17a19dd12916bfc7b5230e8e16ac14050069ed7609f926346912b2a899df21"; + + newSKGuardian = 62446650044403031109669988213557076707788335704243384097041391592912982163892; + newGuardianPubKey = + hex"0410a8e13cb502346e709da19444ffa7584377fd6c68f8a8c3689edef46deac332523d15524394b64c932added00b6a0f9452b2c5cf8fee12e176a10a1dabbd7ba"; + newGuardian = vm.addr(newSKGuardian); + + newGuardianOwnerPublicIdentity = PublicIdentity({ typeId: ALGO_ID_ES256K, key: newGuardianPubKey }); + newGuardianSessionPublicIdentity = PublicIdentity({ typeId: ALGO_ID_ES256K, key: newEnclavePubKey }); } function test_setup() public view { @@ -149,4 +175,191 @@ contract GuardianModuleTest is UnitTestHelper { vm.stopPrank(); } + + function test_rotateGuardianKey_invalid_algorithm() public { + newGuardianOwnerPublicIdentity.typeId = 0; // invalid algorithm + + vm.expectRevert(IGuardianModule.InvalidECDSAPubKey.selector); + guardianModule.rotateGuardianKey( + 0, + abi.encodePacked(newGuardianPubKey, bytes1(0x00)), // invalid length + GuardianSessionProof({ + sessionId: newGuardianSessionId, + sessionKey: newGuardianSessionPublicIdentity, + ownerKey: newGuardianOwnerPublicIdentity, + signature: new bytes(65) + }) + ); + } + + function test_rotateGuardianKey_invalid_owner_key_length() public { + newGuardianOwnerPublicIdentity.key = abi.encodePacked(newGuardianOwnerPublicIdentity.key, bytes1(0x00)); // invalid length + + vm.expectRevert(IGuardianModule.InvalidECDSAPubKey.selector); + guardianModule.rotateGuardianKey( + 0, + abi.encodePacked(newGuardianPubKey, bytes1(0x00)), // invalid length + GuardianSessionProof({ + sessionId: newGuardianSessionId, + sessionKey: newGuardianSessionPublicIdentity, + ownerKey: newGuardianOwnerPublicIdentity, + signature: new bytes(65) + }) + ); + } + + function test_rotateGuardianKey_from_non_guardian_reverts() public { + vm.expectRevert(Unauthorized.selector); + guardianModule.rotateGuardianKey( + 0, + new bytes(65), + GuardianSessionProof({ + sessionId: newGuardianSessionId, + sessionKey: newGuardianSessionPublicIdentity, + ownerKey: newGuardianOwnerPublicIdentity, + signature: new bytes(65) + }) + ); + } + + function test_rotateGuardianKey_invalid_pubkey_length() public { + vm.prank(DAO); + guardianModule.addGuardian(newGuardian); + + vm.expectRevert(IGuardianModule.InvalidECDSAPubKey.selector); + guardianModule.rotateGuardianKey( + 0, + abi.encodePacked(newGuardianPubKey, bytes1(0x00)), // invalid length + GuardianSessionProof({ + sessionId: newGuardianSessionId, + sessionKey: newGuardianSessionPublicIdentity, + ownerKey: newGuardianOwnerPublicIdentity, + signature: new bytes(65) + }) + ); + } + + function test_rotateGuardianKey_stale_evidence() public { + vm.roll(block.number + FRESHNESS_BLOCKS + 1); // move forward in time to make the proof stale + vm.prank(DAO); + guardianModule.addGuardian(newGuardian); + + vm.expectRevert(IGuardianModule.StaleEvidence.selector); + guardianModule.rotateGuardianKey( + 0, + newGuardianPubKey, + GuardianSessionProof({ + sessionId: newGuardianSessionId, + sessionKey: newGuardianSessionPublicIdentity, + ownerKey: newGuardianOwnerPublicIdentity, + signature: new bytes(65) + }) + ); + } + + function test_rotateGuardianKey_invalid_signature() public { + vm.prank(DAO); + guardianModule.addGuardian(newGuardian); + + vm.expectRevert(IGuardianModule.InvalidSignature.selector); + guardianModule.rotateGuardianKey( + 0, + newGuardianPubKey, + GuardianSessionProof({ + sessionId: newGuardianSessionId, + sessionKey: newGuardianSessionPublicIdentity, + ownerKey: newGuardianOwnerPublicIdentity, + signature: new bytes(65) + }) + ); + } + + function test_rotateGuardianKey_invalid_owner_fingerprint() public { + vm.prank(DAO); + guardianModule.addGuardian(newGuardian); + + bytes32 signedMessageHash = + keccak256(abi.encode("ROTATE_GUARDIAN_KEY", address(guardianModule), block.chainid, 0, newEnclavePubKey)); + + (uint8 v, bytes32 r, bytes32 s) = vm.sign(newSKEnclave, signedMessageHash); + bytes memory signature = abi.encodePacked(r, s, v); // note the order here is different from line above. + + sessionRegistryMock.setSessionOwner( + newGuardianSessionId, LibKey.computeKeyFingerprint(newGuardianOwnerPublicIdentity) + ); + + vm.expectRevert(IGuardianModule.InvalidECDSAPubKey.selector); + guardianModule.rotateGuardianKey( + 0, + newEnclavePubKey, + GuardianSessionProof({ + sessionId: newGuardianSessionId, + sessionKey: newGuardianSessionPublicIdentity, + ownerKey: guardian1OwnerPublicIdentity, // invalid owner key (not matching the one used to sign) + signature: signature + }) + ); + } + + function test_rotateGuardianKey_invalid_workload_not_allowed() public { + vm.prank(DAO); + guardianModule.addGuardian(newGuardian); + + bytes32 signedMessageHash = + keccak256(abi.encode("ROTATE_GUARDIAN_KEY", address(guardianModule), block.chainid, 0, newEnclavePubKey)); + + (uint8 v, bytes32 r, bytes32 s) = vm.sign(newSKEnclave, signedMessageHash); + bytes memory signature = abi.encodePacked(r, s, v); // note the order here is different from line above. + + sessionRegistryMock.setSessionOwner( + newGuardianSessionId, LibKey.computeKeyFingerprint(newGuardianOwnerPublicIdentity) + ); + + vm.expectRevert(IGuardianModule.WorkloadNotAllowed.selector); + guardianModule.rotateGuardianKey( + 0, + newEnclavePubKey, + GuardianSessionProof({ + sessionId: newGuardianSessionId, + sessionKey: newGuardianSessionPublicIdentity, + ownerKey: newGuardianOwnerPublicIdentity, + signature: signature + }) + ); + } + + function test_rotateGuardianKey_success() public { + bytes32 workloadId = keccak256("allowed_workload"); + vm.startPrank(DAO); + guardianModule.addGuardian(newGuardian); + guardianModule.setAllowedWorkload(workloadId, true); + vm.stopPrank(); + + bytes32 signedMessageHash = + keccak256(abi.encode("ROTATE_GUARDIAN_KEY", address(guardianModule), block.chainid, 0, newEnclavePubKey)); + + (uint8 v, bytes32 r, bytes32 s) = vm.sign(newSKEnclave, signedMessageHash); + bytes memory signature = abi.encodePacked(r, s, v); // note the order here is different from line above. + + sessionRegistryMock.setSessionOwner( + newGuardianSessionId, LibKey.computeKeyFingerprint(newGuardianOwnerPublicIdentity) + ); + + sessionRegistryMock.setSessionWorkload(newGuardianSessionId, workloadId); + + vm.expectEmit(true, true, true, true); + emit IGuardianModule.RotatedGuardianKey(newGuardian, vm.addr(newSKEnclave), newEnclavePubKey); + guardianModule.rotateGuardianKey( + 0, + newEnclavePubKey, + GuardianSessionProof({ + sessionId: newGuardianSessionId, + sessionKey: newGuardianSessionPublicIdentity, + ownerKey: newGuardianOwnerPublicIdentity, + signature: signature + }) + ); + + assertEq(guardianModule.getGuardiansEnclaveAddress(newGuardian), vm.addr(newSKEnclave), "bad enclave address"); + } } From 30ec6afddbb171803d5c4383bc0c598955f6aeb1 Mon Sep 17 00:00:00 2001 From: Eladio Date: Thu, 5 Mar 2026 11:14:05 +0100 Subject: [PATCH 36/51] Updated addresses and selected submodule branch --- .gitmodules | 1 + mainnet-contracts/script/DeployerHelper.s.sol | 52 +++++++++---------- ...GenerateBLSKeysAndRegisterValidators.s.sol | 6 +-- .../PufferModuleManager.integration.t.sol | 2 +- ...fferModuleManagerSlasher.integration.t.sol | 4 +- .../ffi/PufferModuleManagerHoodiFfi.t.sol | 15 +++--- 6 files changed, 39 insertions(+), 41 deletions(-) diff --git a/.gitmodules b/.gitmodules index a04c15e3..50abe928 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,4 @@ [submodule "mainnet-contracts/lib/automata-tee-workload-measurement"] path = mainnet-contracts/lib/automata-tee-workload-measurement url = https://github.com/automata-network/automata-tee-workload-measurement + branch = develop diff --git a/mainnet-contracts/script/DeployerHelper.s.sol b/mainnet-contracts/script/DeployerHelper.s.sol index 58616180..1ac50d11 100644 --- a/mainnet-contracts/script/DeployerHelper.s.sol +++ b/mainnet-contracts/script/DeployerHelper.s.sol @@ -166,8 +166,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x99c3E46E575df251149866285DdA7DAEba875B71 return 0x99c3E46E575df251149866285DdA7DAEba875B71; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0x6a5c73AB3e5Bc3675A2e1CCcc46aF6796db36BC8 - return 0x6a5c73AB3e5Bc3675A2e1CCcc46aF6796db36BC8; + // https://hoodi.etherscan.io/address/0xdfC5D871feB2Cb34f54f0c7f6c3DaeD2eA4494Ec + return 0xdfC5D871feB2Cb34f54f0c7f6c3DaeD2eA4494Ec; } revert("RestakingOperatorBeacon not available for this chain"); @@ -198,8 +198,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x0910310130d1c062DEF8B807528bdac80203BC66 return 0x0910310130d1c062DEF8B807528bdac80203BC66; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0x57bC9fDcd05bD53bCe1B2db3a50Eb5948Bd4e5c7 - return 0x57bC9fDcd05bD53bCe1B2db3a50Eb5948Bd4e5c7; + // https://hoodi.etherscan.io/address/0xBD66e6d22FC0147AA82b5eb6A8A3FEEC99BB4567 + return 0xBD66e6d22FC0147AA82b5eb6A8A3FEEC99BB4567; } revert("GuardianModule not available for this chain"); @@ -214,8 +214,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x4B0542470935ed4b085C3AD1983E85f5623ABf89 return 0x4B0542470935ed4b085C3AD1983E85f5623ABf89; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0x6899d0dE991458929b43e3DE4fC2d4A9ca7E4673 - return 0x6899d0dE991458929b43e3DE4fC2d4A9ca7E4673; + // https://hoodi.etherscan.io/address/0xd8E4EC18c776E6d9391b0F386e653A246e986Eb9 + return 0xd8E4EC18c776E6d9391b0F386e653A246e986Eb9; } revert("PufferModuleBeacon not available for this chain"); @@ -262,8 +262,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x09BE86B01c1e32dCa2ebdEDb01cD5A3F798b80C5 return 0x09BE86B01c1e32dCa2ebdEDb01cD5A3F798b80C5; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0x5150F12A6f5a3D071A84442a671a4B234B53beC4 - return 0x5150F12A6f5a3D071A84442a671a4B234B53beC4; + // https://hoodi.etherscan.io/address/0x58c3FCfdB032Fca20786C779bcD1026A79e94Def + return 0x58c3FCfdB032Fca20786C779bcD1026A79e94Def; } revert("AVSContractsRegistry not available for this chain"); @@ -278,8 +278,8 @@ abstract contract DeployerHelper is Script { // Holesky Timelock: https://explorer.pops.one/address/0x829aF0B3d099a12F0aE1b806f466EF771E2C07F8 return 0x829aF0B3d099a12F0aE1b806f466EF771E2C07F8; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0xD256D160598ba8e068fC62C7fED46694CdD48762 - return 0xD256D160598ba8e068fC62C7fED46694CdD48762; + // https://hoodi.etherscan.io/address/0x6D1D7F0a2f2aD141717505c95F470bd716C1A31a + return 0x6D1D7F0a2f2aD141717505c95F470bd716C1A31a; } revert("Timelock not available for this chain"); @@ -369,8 +369,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x8e043ed3F06720615685D4978770Cd5C8fe90fe3 return 0x8e043ed3F06720615685D4978770Cd5C8fe90fe3; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0xF232Df3a714c99C05100571644b6d4AA1000ee4E - return 0xF232Df3a714c99C05100571644b6d4AA1000ee4E; + // https://hoodi.etherscan.io/address/0x7e55a507c0AEA17c7d344AEC91897674989E8233 + return 0x7e55a507c0AEA17c7d344AEC91897674989E8233; } revert("puffer oracle not available for this chain"); @@ -401,8 +401,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x1d181cBd1825e9eBC6AD966878D555A7215FF4F0 return 0x1d181cBd1825e9eBC6AD966878D555A7215FF4F0; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0x06EDa6073b3dE1B1Dfd58cb5615fD8188C114a88 - return 0x06EDa6073b3dE1B1Dfd58cb5615fD8188C114a88; + // https://hoodi.etherscan.io/address/0x6E9C82F6002B03cbC105D4e77d1da16C3f067035 + return 0x6E9C82F6002B03cbC105D4e77d1da16C3f067035; } revert("WETH not available for this chain"); @@ -436,8 +436,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x180a345906e42293dcAd5CCD9b0e1DB26aE0274e return 0x180a345906e42293dcAd5CCD9b0e1DB26aE0274e; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0x0950195ac9b310815698f5dded3bd32814f46efd - return 0x0950195AC9B310815698f5dDeD3BD32814f46EFD; + // https://hoodi.etherscan.io/address/0x519C59FeaD8D65A5a3Fa331634ce5E69508dD36d + return 0x519C59FeaD8D65A5a3Fa331634ce5E69508dD36d; } else if (block.chainid == binance) { // https://bscscan.com/address/0x8849e9eB8bb27c1916AfB17ee4dEcAd375916474 return 0x8849e9eB8bb27c1916AfB17ee4dEcAd375916474; @@ -465,8 +465,8 @@ abstract contract DeployerHelper is Script { // https://sepolia.etherscan.io/address/0xd85D701A660a61D9737D05397612EF08be2cE62D return 0xd85D701A660a61D9737D05397612EF08be2cE62D; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0x3248c7b9D2c8e427A2752cA2339166830FA83479 - return 0x3248c7b9D2c8e427A2752cA2339166830FA83479; + // https://hoodi.etherscan.io/address/0xFA138bFbb09c743077CeBbD2F979586F690450EB + return 0xFA138bFbb09c743077CeBbD2F979586F690450EB; } revert("PufferVault not available for this chain"); @@ -481,8 +481,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0x20377c306451140119C9967Ba6D0158a05b4eD07 return 0x20377c306451140119C9967Ba6D0158a05b4eD07; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0x26eEa064e7Ed6b52847f8153Cd466A7b01f2cB14 - return 0x26eEa064e7Ed6b52847f8153Cd466A7b01f2cB14; + // https://hoodi.etherscan.io/address/0x2E6a94456014B1b152fdCF5e047c793b1E36F3D4 + return 0x2E6a94456014B1b152fdCF5e047c793b1E36F3D4; } revert("PufferModuleManager not available for this chain"); @@ -497,8 +497,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0xB028194785178a94Fe608994A4d5AD84c285A640 return 0xB028194785178a94Fe608994A4d5AD84c285A640; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0x032E3fF6716084Bd8D50a35f1cfC9a22cEeB0355 - return 0x032E3fF6716084Bd8D50a35f1cfC9a22cEeB0355; + // https://hoodi.etherscan.io/address/0x06034E7004F3465C3458376E08c129E47a650596 + return 0x06034E7004F3465C3458376E08c129E47a650596; } revert("ValidatorTicket not available for this chain"); @@ -513,8 +513,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/0xE00c79408B9De5BaD2FDEbB1688997a68eC988CD return 0xE00c79408B9De5BaD2FDEbB1688997a68eC988CD; } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0xa3eca8ef718538Fc2610899e95590B521D59a842 - return 0xa3eca8ef718538Fc2610899e95590B521D59a842; + // https://hoodi.etherscan.io/address/0x6ECcBAB07B8e592D9e5Ab9042EF2CacF1eff1155 + return 0x6ECcBAB07B8e592D9e5Ab9042EF2CacF1eff1155; } revert("PufferProtocol not available for this chain"); @@ -529,8 +529,8 @@ abstract contract DeployerHelper is Script { // https://holesky.etherscan.io/address/- return address(0); } else if (block.chainid == hoodi) { - // https://hoodi.etherscan.io/address/0xa3eca8ef718538Fc2610899e95590B521D59a842 - return 0xa3eca8ef718538Fc2610899e95590B521D59a842; + // https://hoodi.etherscan.io/address/0xe2223294EDf1658f57f3872e249007C31dE9aD43 + return 0xe2223294EDf1658f57f3872e249007C31dE9aD43; } revert("RestakingOperatorController not available for this chain"); diff --git a/mainnet-contracts/script/GenerateBLSKeysAndRegisterValidators.s.sol b/mainnet-contracts/script/GenerateBLSKeysAndRegisterValidators.s.sol index 5a9216b2..1052838c 100644 --- a/mainnet-contracts/script/GenerateBLSKeysAndRegisterValidators.s.sol +++ b/mainnet-contracts/script/GenerateBLSKeysAndRegisterValidators.s.sol @@ -45,7 +45,7 @@ contract GenerateBLSKeysAndRegisterValidators is Script { forkVersion = "0x01017000"; } else if (block.chainid == 560048) { // Hoodi - protocolAddress = 0xa3eca8ef718538Fc2610899e95590B521D59a842; + protocolAddress = 0x6ECcBAB07B8e592D9e5Ab9042EF2CacF1eff1155; pufferProtocol = PufferProtocol(protocolAddress); forkVersion = "0x10000910"; } else if (block.chainid == 1) { @@ -174,9 +174,7 @@ contract GenerateBLSKeysAndRegisterValidators is Script { // Generates a new validator key using coral https://github.com/PufferFinance/coral/tree/main function _generateValidatorKey(uint256 idx, bytes32 moduleName) internal { uint256 numberOfGuardians = pufferProtocol.GUARDIAN_MODULE().getGuardians().length; - // bytes[] memory guardianPubKeys = pufferProtocol.GUARDIAN_MODULE().getGuardiansEnclavePubkeys(); // This is now deprecated - //TODO Update this if needed - bytes[] memory guardianPubKeys = new bytes[](numberOfGuardians); + bytes[] memory guardianPubKeys = pufferProtocol.GUARDIAN_MODULE().getGuardiansEnclavePubkeys(); address moduleAddress = IPufferProtocol(protocolAddress).getModuleAddress(moduleName); bytes memory withdrawalCredentials = IPufferProtocol(protocolAddress).getWithdrawalCredentials(moduleAddress); diff --git a/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol b/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol index c0c6197e..dca30760 100644 --- a/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol +++ b/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol @@ -30,7 +30,7 @@ contract PufferModuleManagerIntegrationTest is IntegrationTestHelper { address EIGEN_DA_SERVICE_MANAGER = 0x3FF2204A567C15dC3731140B95362ABb4b17d8ED; // IAVSDirectory public avsDirectory = IAVSDirectory(0x055733000064333CaDDbC92763c58BF0192fFeBf); - address private constant HOODI_WETH_ADDRESS = 0x06EDa6073b3dE1B1Dfd58cb5615fD8188C114a88; + address private constant HOODI_WETH_ADDRESS = 0x6E9C82F6002B03cbC105D4e77d1da16C3f067035; address private constant HOODI_STRATEGY_MANAGER = 0xeE45e76ddbEDdA2918b8C7E3035cd37Eab3b5D41; address private constant HOODI_WETH_STRATEGY = 0x24579aD4fe83aC53546E5c2D3dF5F85D6383420d; address private constant HOODI_DELEGATION_MANAGER = 0x867837a9722C512e0862d8c2E15b8bE220E8b87d; diff --git a/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol b/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol index 64176e3a..cf60609e 100644 --- a/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol +++ b/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol @@ -19,8 +19,8 @@ import { RestakingOperatorController } from "../../src/RestakingOperatorControll contract PufferModuleManagerSlasherIntegrationTest is Test, DeployerHelper { PufferModuleManager public pufferModuleManager; - address PUFFER_MODULE_0_HOODI = 0xeaA758DC50180ac70Ec69A241f8a866e6e852905; - address EIGENPOD_0_HOODI = 0x17F9D0ffAAeF968d2c44807Cf3c96D504e640cA8; + address PUFFER_MODULE_0_HOODI = 0x1086349d358fa589641e8a7440d46E5EE8A683C5; + address EIGENPOD_0_HOODI = 0x8F0b1e0B974C8b91D69C6A62E0710e3F497943e0; address RESTAKING_OPERATOR_0_HOODI = address(0); // TODO Change bytes32 PUFFER_MODULE_0_NAME = bytes32("PUFFER_MODULE_0"); diff --git a/mainnet-contracts/test/fork-tests/ffi/PufferModuleManagerHoodiFfi.t.sol b/mainnet-contracts/test/fork-tests/ffi/PufferModuleManagerHoodiFfi.t.sol index dbf12733..d824cb27 100644 --- a/mainnet-contracts/test/fork-tests/ffi/PufferModuleManagerHoodiFfi.t.sol +++ b/mainnet-contracts/test/fork-tests/ffi/PufferModuleManagerHoodiFfi.t.sol @@ -19,20 +19,19 @@ contract PufferModuleManagerHoodiTestnetFFI is Test { uint256[] privKeys; // https://github.com/Layr-Labs/eigenlayer-contracts?tab=readme-ov-file#deployments - address EIGEN_DA_REGISTRY_COORDINATOR_HOODI = 0x53012C69A189cfA2D9d29eb6F19B32e0A2EA3490; // TODO Change - address EIGEN_DA_SERVICE_MANAGER = 0xD4A7E1Bd8015057293f0D0A557088c286942e84b; // TODO Change + address EIGEN_DA_REGISTRY_COORDINATOR_HOODI = 0xB5b76D561eeF36CD772890C94C6Bde8b895455e2; + address EIGEN_DA_SERVICE_MANAGER = 0x3FF2204A567C15dC3731140B95362ABb4b17d8ED; address BEACON_CHAIN_STRATEGY = 0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0; address EIGEN_POD_MANAGER = 0xcd1442415Fc5C29Aa848A49d2e232720BE07976c; - address DELAYED_WITHDRAWAL_ROUTER = 0x642c646053eaf2254f088e9019ACD73d9AE0FA32; // TODO Change address DELEGATION_MANAGER = 0x867837a9722C512e0862d8c2E15b8bE220E8b87d; // Puffer Hoodi deployment address PUFFER_SHARED_DEV_WALLET = 0xeeE554b5b2bF5FBc9730Ce33c6dc92828DA01BeE; - address ACCESS_MANAGER_HOODI = 0x0950195AC9B310815698f5dDeD3BD32814f46EFD; - address MODULE_BEACON_HOODI = 0x6899d0dE991458929b43e3DE4fC2d4A9ca7E4673; - address PUFFER_PROTOCOL_HOODI = 0xa3eca8ef718538Fc2610899e95590B521D59a842; - address PUFFER_MODULE_MANAGER = 0x26eEa064e7Ed6b52847f8153Cd466A7b01f2cB14; - address PUFFER_MODULE_0_HOODI = 0xeaA758DC50180ac70Ec69A241f8a866e6e852905; + address ACCESS_MANAGER_HOODI = 0x519C59FeaD8D65A5a3Fa331634ce5E69508dD36d; + address MODULE_BEACON_HOODI = 0xd8E4EC18c776E6d9391b0F386e653A246e986Eb9; + address PUFFER_PROTOCOL_HOODI = 0x6ECcBAB07B8e592D9e5Ab9042EF2CacF1eff1155; + address PUFFER_MODULE_MANAGER = 0x2E6a94456014B1b152fdCF5e047c793b1E36F3D4; + address PUFFER_MODULE_0_HOODI = 0x1086349d358fa589641e8a7440d46E5EE8A683C5; // https://hoodi.eigenlayer.xyz/operator/0xe2c2dc296a0bff351f6bc3e98d37ea798e393e56 // TODO Change address RESTAKING_OPERATOR_CONTRACT = 0xe2c2dc296a0bFF351F6bC3e98D37ea798e393e56; // TODO Change address RESTAKING_OPERATOR_BEACON = 0x9f9aa46c3b98aDDc1eEef87De25f986024f7C6Bb; From 656d14cb5a8e0b79ef3b210d1b2fa1a6f05797ba Mon Sep 17 00:00:00 2001 From: Eladio Date: Thu, 5 Mar 2026 11:40:31 +0100 Subject: [PATCH 37/51] Updated github workflows --- .github/workflows/mainnet-contracts.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/mainnet-contracts.yml b/.github/workflows/mainnet-contracts.yml index 8701c2bd..2bd196e2 100644 --- a/.github/workflows/mainnet-contracts.yml +++ b/.github/workflows/mainnet-contracts.yml @@ -19,6 +19,7 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 + submodules: recursive - name: Codespell uses: codespell-project/actions-codespell@v2.0 @@ -35,6 +36,8 @@ jobs: uses: styfle/cancel-workflow-action@0.12.1 - uses: actions/checkout@v4 + with: + submodules: recursive - uses: actions/setup-node@v4 with: cache: "yarn" @@ -83,6 +86,8 @@ jobs: uses: styfle/cancel-workflow-action@0.12.1 - uses: actions/checkout@v4 + with: + submodules: recursive - uses: actions/setup-node@v4 with: cache: "yarn" From 2a8d828efe976ff205bc8d8b380cf0640f341a79 Mon Sep 17 00:00:00 2001 From: Eladio Date: Thu, 5 Mar 2026 12:42:13 +0100 Subject: [PATCH 38/51] Updated fork block and skipped lib from codespell --- .github/workflows/mainnet-contracts.yml | 2 +- .../fork-tests/PufferModuleManagerSlasher.integration.t.sol | 2 +- mainnet-contracts/test/helpers/IntegrationTestHelper.sol | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/mainnet-contracts.yml b/.github/workflows/mainnet-contracts.yml index 2bd196e2..e5d43149 100644 --- a/.github/workflows/mainnet-contracts.yml +++ b/.github/workflows/mainnet-contracts.yml @@ -27,7 +27,7 @@ jobs: path: mainnet-contracts check_hidden: true check_filenames: true - skip: "pnpm-lock.yaml" + skip: "pnpm-lock.yaml,./mainnet-contracts/lib" tests: runs-on: ubuntu-latest diff --git a/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol b/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol index cf60609e..4a266cce 100644 --- a/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol +++ b/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol @@ -28,7 +28,7 @@ contract PufferModuleManagerSlasherIntegrationTest is Test, DeployerHelper { DeployPufferModuleImplementation deployPufferModule; DeployRestakingOperator deployRestakingOperator; - uint32 START_BLOCK = 2994229; // Dec-23-2024 09:43:00 AM +UTC // TODO Change + uint32 START_BLOCK = 2_260_721; // Feb-18-2026 03:43:24 PM +UTC function setUp() public { vm.createSelectFork(vm.rpcUrl("hoodi"), START_BLOCK); diff --git a/mainnet-contracts/test/helpers/IntegrationTestHelper.sol b/mainnet-contracts/test/helpers/IntegrationTestHelper.sol index 7ee2d094..bbc3e6a1 100644 --- a/mainnet-contracts/test/helpers/IntegrationTestHelper.sol +++ b/mainnet-contracts/test/helpers/IntegrationTestHelper.sol @@ -48,7 +48,7 @@ contract IntegrationTestHelper is Test { // 'default' block number function deployContractsHoodi() public virtual { - deployContractsHoodi(2_260_721); + deployContractsHoodi(2_260_721); // Feb-18-2026 03:43:24 PM +UTC } function _deployAndLabel(address[] memory guardians, uint256 threshold) internal { From 1a50dbbf0348ed180420890625db33515d292ae9 Mon Sep 17 00:00:00 2001 From: Eladio Date: Thu, 5 Mar 2026 13:08:48 +0100 Subject: [PATCH 39/51] Uppdated hoodi fork block number --- .github/workflows/mainnet-contracts.yml | 2 +- .../fork-tests/PufferModuleManagerSlasher.integration.t.sol | 2 +- mainnet-contracts/test/helpers/IntegrationTestHelper.sol | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/mainnet-contracts.yml b/.github/workflows/mainnet-contracts.yml index e5d43149..9835a8b6 100644 --- a/.github/workflows/mainnet-contracts.yml +++ b/.github/workflows/mainnet-contracts.yml @@ -27,7 +27,7 @@ jobs: path: mainnet-contracts check_hidden: true check_filenames: true - skip: "pnpm-lock.yaml,./mainnet-contracts/lib" + skip: "pnpm-lock.yaml,*/lib/*" tests: runs-on: ubuntu-latest diff --git a/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol b/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol index 4a266cce..b7efc51e 100644 --- a/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol +++ b/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol @@ -28,7 +28,7 @@ contract PufferModuleManagerSlasherIntegrationTest is Test, DeployerHelper { DeployPufferModuleImplementation deployPufferModule; DeployRestakingOperator deployRestakingOperator; - uint32 START_BLOCK = 2_260_721; // Feb-18-2026 03:43:24 PM +UTC + uint32 START_BLOCK = 2352200; // Mar-04-2026 05:17:12 PM +UTC function setUp() public { vm.createSelectFork(vm.rpcUrl("hoodi"), START_BLOCK); diff --git a/mainnet-contracts/test/helpers/IntegrationTestHelper.sol b/mainnet-contracts/test/helpers/IntegrationTestHelper.sol index bbc3e6a1..0521b009 100644 --- a/mainnet-contracts/test/helpers/IntegrationTestHelper.sol +++ b/mainnet-contracts/test/helpers/IntegrationTestHelper.sol @@ -48,7 +48,7 @@ contract IntegrationTestHelper is Test { // 'default' block number function deployContractsHoodi() public virtual { - deployContractsHoodi(2_260_721); // Feb-18-2026 03:43:24 PM +UTC + deployContractsHoodi(2352200); // Mar-04-2026 05:17:12 PM +UTC } function _deployAndLabel(address[] memory guardians, uint256 threshold) internal { From 3040b438e4d8d9a7c52c6779d8c940dcf1a5b953 Mon Sep 17 00:00:00 2001 From: Eladio Date: Thu, 5 Mar 2026 17:59:42 +0100 Subject: [PATCH 40/51] Fixed tests (WIP) --- mainnet-contracts/script/DeployPufferModuleImplementation.s.sol | 1 + mainnet-contracts/script/DeployerHelper.s.sol | 1 + .../test/fork-tests/PufferModuleManager.integration.t.sol | 2 ++ mainnet-contracts/test/helpers/IntegrationTestHelper.sol | 2 +- 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/mainnet-contracts/script/DeployPufferModuleImplementation.s.sol b/mainnet-contracts/script/DeployPufferModuleImplementation.s.sol index ab1a0ce9..886f9faa 100644 --- a/mainnet-contracts/script/DeployPufferModuleImplementation.s.sol +++ b/mainnet-contracts/script/DeployPufferModuleImplementation.s.sol @@ -65,5 +65,6 @@ contract DeployPufferModuleImplementation is DeployerHelper { if (block.chainid == holesky) { AccessManager(_getAccessManager()).execute(_getPufferModuleBeacon(), cd); } + vm.stopPrank(); } } diff --git a/mainnet-contracts/script/DeployerHelper.s.sol b/mainnet-contracts/script/DeployerHelper.s.sol index 1ac50d11..513e32f5 100644 --- a/mainnet-contracts/script/DeployerHelper.s.sol +++ b/mainnet-contracts/script/DeployerHelper.s.sol @@ -115,6 +115,7 @@ abstract contract DeployerHelper is Script { console.logBytes(upgradeCallData); console.log("================================================"); } + vm.stopPrank(); } function _getBeaconChainStrategy() internal view returns (address) { diff --git a/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol b/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol index dca30760..555d35dc 100644 --- a/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol +++ b/mainnet-contracts/test/fork-tests/PufferModuleManager.integration.t.sol @@ -42,6 +42,7 @@ contract PufferModuleManagerIntegrationTest is IntegrationTestHelper { function test_create_puffer_module() public { vm.startPrank(DAO); pufferProtocol.createPufferModule(bytes32("SOME_MODULE_NAME")); + vm.stopPrank(); } function _depositToWETHEigenLayerStrategyAndDelegateTo(address restakingOperator) internal { @@ -56,6 +57,7 @@ contract PufferModuleManagerIntegrationTest is IntegrationTestHelper { ISignatureUtils.SignatureWithExpiry memory signatureWithExpiry; IDelegationManager(HOODI_DELEGATION_MANAGER).delegateTo(restakingOperator, signatureWithExpiry, bytes32(0)); + vm.stopPrank(); } // Creates a new restaking operator and returns it diff --git a/mainnet-contracts/test/helpers/IntegrationTestHelper.sol b/mainnet-contracts/test/helpers/IntegrationTestHelper.sol index 0521b009..e17d18b2 100644 --- a/mainnet-contracts/test/helpers/IntegrationTestHelper.sol +++ b/mainnet-contracts/test/helpers/IntegrationTestHelper.sol @@ -14,7 +14,7 @@ import { ISessionRegistry } from "@automata-network/automata-tee-workload-measurement/interfaces/registries/ISessionRegistry.sol"; contract IntegrationTestHelper is Test { - address DAO = 0xeeE554b5b2bF5FBc9730Ce33c6dc92828DA01BeE; + address DAO = 0xC4a2E012024d4ff28a4E2334F58D4Cc233EB1FE1; PufferProtocol public pufferProtocol; UpgradeableBeacon public beacon; PufferModuleManager public moduleManager; From fa4f8dccc43b23afb57afc2137fd1ea74c2a2170 Mon Sep 17 00:00:00 2001 From: Eladio Date: Tue, 10 Mar 2026 18:03:39 +0100 Subject: [PATCH 41/51] Removed rave from ValidatorKeyData and only using 2 ETH bond now --- ...GenerateBLSKeysAndRegisterValidators.s.sol | 3 +- mainnet-contracts/src/PufferProtocol.sol | 27 +-- .../src/interface/IPufferProtocol.sol | 5 +- .../src/struct/ValidatorKeyData.sol | 3 +- ...fferModuleManagerSlasher.integration.t.sol | 8 + .../test/handlers/PufferProtocolHandler.sol | 7 +- .../test/unit/PufferProtocol.t.sol | 186 +++++++++--------- 7 files changed, 112 insertions(+), 127 deletions(-) diff --git a/mainnet-contracts/script/GenerateBLSKeysAndRegisterValidators.s.sol b/mainnet-contracts/script/GenerateBLSKeysAndRegisterValidators.s.sol index 1052838c..7404434b 100644 --- a/mainnet-contracts/script/GenerateBLSKeysAndRegisterValidators.s.sol +++ b/mainnet-contracts/script/GenerateBLSKeysAndRegisterValidators.s.sol @@ -108,8 +108,7 @@ contract GenerateBLSKeysAndRegisterValidators is Script { signature: stdJson.readBytes(registrationJson, ".signature"), depositDataRoot: stdJson.readBytes32(registrationJson, ".deposit_data_root"), blsEncryptedPrivKeyShares: blsEncryptedPrivKeyShares, - blsPubKeySet: stdJson.readBytes(registrationJson, ".bls_pub_key_set"), - raveEvidence: "" + blsPubKeySet: stdJson.readBytes(registrationJson, ".bls_pub_key_set") }); Permit memory pufETHPermit = _signPermit({ diff --git a/mainnet-contracts/src/PufferProtocol.sol b/mainnet-contracts/src/PufferProtocol.sol index d910547e..dbb6e391 100644 --- a/mainnet-contracts/src/PufferProtocol.sol +++ b/mainnet-contracts/src/PufferProtocol.sol @@ -56,14 +56,9 @@ contract PufferProtocol is IPufferProtocol, AccessManagedUpgradeable, UUPSUpgrad uint256 internal constant _BLS_PUB_KEY_LENGTH = 48; /** - * @dev ETH Amount required to be deposited as a bond if the node operator uses SGX + * @dev ETH Amount required to be deposited as a bond */ - uint256 internal constant _ENCLAVE_VALIDATOR_BOND = 1 ether; - - /** - * @dev ETH Amount required to be deposited as a bond if the node operator doesn't use SGX - */ - uint256 internal constant _NO_ENCLAVE_VALIDATOR_BOND = 2 ether; + uint256 internal constant VALIDATOR_BOND = 2 ether; /** * @dev Default "PUFFER_MODULE_0" module @@ -198,14 +193,11 @@ contract PufferProtocol is IPufferProtocol, AccessManagedUpgradeable, UUPSUpgrad _checkValidatorRegistrationInputs({ $: $, data: data, moduleName: moduleName }); - uint256 validatorBondInETH = data.raveEvidence.length > 0 ? _ENCLAVE_VALIDATOR_BOND : _NO_ENCLAVE_VALIDATOR_BOND; - - // If the node operator is paying for the bond in ETH and wants to transfer VT from their wallet, the ETH amount they send must be equal the bond amount - if (vtPermit.amount != 0 && pufETHPermit.amount == 0 && msg.value != validatorBondInETH) { + if (vtPermit.amount != 0 && pufETHPermit.amount == 0 && msg.value != VALIDATOR_BOND) { revert InvalidETHAmount(); } - uint256 vtPayment = pufETHPermit.amount == 0 ? msg.value - validatorBondInETH : msg.value; + uint256 vtPayment = pufETHPermit.amount == 0 ? msg.value - VALIDATOR_BOND : msg.value; uint256 receivedVtAmount; // If the VT permit amount is zero, that means that the user is paying for VT with ETH @@ -228,10 +220,10 @@ contract PufferProtocol is IPufferProtocol, AccessManagedUpgradeable, UUPSUpgrad // If the pufETH permit amount is zero, that means that the user is paying the bond with ETH if (pufETHPermit.amount == 0) { // Mint pufETH by depositing ETH and store the bond amount - bondAmount = PUFFER_VAULT.depositETH{ value: validatorBondInETH }(address(this)); + bondAmount = PUFFER_VAULT.depositETH{ value: VALIDATOR_BOND }(address(this)); } else { // Calculate the pufETH amount that we need to transfer from the user - bondAmount = PUFFER_VAULT.convertToShares(validatorBondInETH); + bondAmount = PUFFER_VAULT.convertToShares(VALIDATOR_BOND); _callPermit(address(PUFFER_VAULT), pufETHPermit); // slither-disable-next-line unchecked-transfer @@ -612,7 +604,7 @@ contract PufferProtocol is IPufferProtocol, AccessManagedUpgradeable, UUPSUpgrad /** * @notice Returns necessary information to make Guardian's life easier */ - function getPayload(bytes32 moduleName, bool usingEnclave) + function getPayload(bytes32 moduleName) external view returns (bytes[] memory, bytes memory, uint256, uint256) @@ -622,8 +614,7 @@ contract PufferProtocol is IPufferProtocol, AccessManagedUpgradeable, UUPSUpgrad bytes[] memory pubKeys = GUARDIAN_MODULE.getGuardiansEnclavePubkeys(); bytes memory withdrawalCredentials = getWithdrawalCredentials(address($.modules[moduleName])); uint256 threshold = GUARDIAN_MODULE.getThreshold(); - uint256 validatorBond = usingEnclave ? _ENCLAVE_VALIDATOR_BOND : _NO_ENCLAVE_VALIDATOR_BOND; - uint256 ethAmount = validatorBond + ($.minimumVtAmount * PUFFER_ORACLE.getValidatorTicketPrice()) / 1 ether; + uint256 ethAmount = VALIDATOR_BOND + ($.minimumVtAmount * PUFFER_ORACLE.getValidatorTicketPrice()) / 1 ether; return (pubKeys, withdrawalCredentials, threshold, ethAmount); } @@ -669,7 +660,7 @@ contract PufferProtocol is IPufferProtocol, AccessManagedUpgradeable, UUPSUpgrad ++$.moduleLimits[moduleName].numberOfRegisteredValidators; } emit NumberOfRegisteredValidatorsChanged(moduleName, $.moduleLimits[moduleName].numberOfRegisteredValidators); - emit ValidatorKeyRegistered(data.blsPubKey, pufferModuleIndex, moduleName, (data.raveEvidence.length > 0)); + emit ValidatorKeyRegistered(data.blsPubKey, pufferModuleIndex, moduleName); } function _setValidatorLimitPerModule(bytes32 moduleName, uint128 limit) internal { diff --git a/mainnet-contracts/src/interface/IPufferProtocol.sol b/mainnet-contracts/src/interface/IPufferProtocol.sol index f6a87a69..d381ab2e 100644 --- a/mainnet-contracts/src/interface/IPufferProtocol.sol +++ b/mainnet-contracts/src/interface/IPufferProtocol.sol @@ -145,11 +145,10 @@ interface IPufferProtocol { * @param pubKey is the validator public key * @param pufferModuleIndex is the internal validator index in Puffer Finance, not to be mistaken with validator index on Beacon Chain * @param moduleName is the staking Module - * @param usingEnclave is indicating if the validator is using secure enclave - * @dev Signature "0xc73344cf227e056eee8d82aee54078c9b55323b61d17f61587eb570873f8e319" + * @dev Signature "0x6b9febc68231d6c196b22b02f442fa6dc3148ee90b6e83d5b978c11833587159" */ event ValidatorKeyRegistered( - bytes pubKey, uint256 indexed pufferModuleIndex, bytes32 indexed moduleName, bool usingEnclave + bytes pubKey, uint256 indexed pufferModuleIndex, bytes32 indexed moduleName ); /** diff --git a/mainnet-contracts/src/struct/ValidatorKeyData.sol b/mainnet-contracts/src/struct/ValidatorKeyData.sol index 78512fbd..49380cd4 100644 --- a/mainnet-contracts/src/struct/ValidatorKeyData.sol +++ b/mainnet-contracts/src/struct/ValidatorKeyData.sol @@ -10,5 +10,4 @@ struct ValidatorKeyData { bytes32 depositDataRoot; bytes[] blsEncryptedPrivKeyShares; bytes blsPubKeySet; - bytes raveEvidence; -} +} \ No newline at end of file diff --git a/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol b/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol index b7efc51e..8e3a1bb7 100644 --- a/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol +++ b/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol @@ -6,6 +6,7 @@ import { DeployerHelper } from "../../script/DeployerHelper.s.sol"; import { DeployEverything } from "script/DeployEverything.s.sol"; import { DeployEverything } from "script/DeployEverything.s.sol"; import { PufferModuleManager } from "../../src/PufferModuleManager.sol"; +import { PufferProtocol } from "../../src/PufferProtocol.sol"; import { IStrategy } from "../../src/interface/Eigenlayer-Slashing/IStrategy.sol"; import { IDelegationManagerTypes } from "../../src/interface/Eigenlayer-Slashing/IDelegationManager.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; @@ -51,6 +52,13 @@ contract PufferModuleManagerSlasherIntegrationTest is Test, DeployerHelper { deployRestakingOperator.deployRestakingOperatorTests(address(reOpController)); pufferModuleManager = PufferModuleManager(payable(_getPufferModuleManager())); + + PufferProtocol pufferProtocol = PufferProtocol(_getPufferProtocol()); + + vm.label(address(pufferModuleManager), "PufferModuleManager"); + vm.label(address(pufferProtocol), "PufferProtocol"); + vm.label(address(pufferModuleManager.authority()), "AccessManager"); + vm.label(pufferProtocol.getModuleAddress(PUFFER_MODULE_0_NAME), "PufferModule0"); } // Queue new withdrawals diff --git a/mainnet-contracts/test/handlers/PufferProtocolHandler.sol b/mainnet-contracts/test/handlers/PufferProtocolHandler.sol index 95892bcd..c0d30679 100644 --- a/mainnet-contracts/test/handlers/PufferProtocolHandler.sol +++ b/mainnet-contracts/test/handlers/PufferProtocolHandler.sol @@ -552,8 +552,7 @@ contract PufferProtocolHandler is Test { withdrawalCredentials: withdrawalCredentials }), blsEncryptedPrivKeyShares: new bytes[](3), - blsPubKeySet: new bytes(48), - raveEvidence: new bytes(1) // Guardians are checking it off chain + blsPubKeySet: new bytes(48) }); return validatorData; @@ -583,10 +582,10 @@ contract PufferProtocolHandler is Test { uint256 idx = pufferProtocol.getPendingValidatorIndex(moduleName); - uint256 bond = 1 ether; + uint256 bond = 2 ether; vm.expectEmit(true, true, true, true); - emit IPufferProtocol.ValidatorKeyRegistered(pubKey, idx, moduleName, true); + emit IPufferProtocol.ValidatorKeyRegistered(pubKey, idx, moduleName); pufferProtocol.registerValidatorKey{ value: (smoothingCommitment + bond) }( validatorKeyData, moduleName, emptyPermit, emptyPermit ); diff --git a/mainnet-contracts/test/unit/PufferProtocol.t.sol b/mainnet-contracts/test/unit/PufferProtocol.t.sol index bff105a3..922937e9 100644 --- a/mainnet-contracts/test/unit/PufferProtocol.t.sol +++ b/mainnet-contracts/test/unit/PufferProtocol.t.sol @@ -20,7 +20,7 @@ import { StoppedValidatorInfo } from "../../src/struct/StoppedValidatorInfo.sol" contract PufferProtocolTest is UnitTestHelper { using ECDSA for bytes32; - event ValidatorKeyRegistered(bytes pubKey, uint256 indexed, bytes32 indexed, bool); + event ValidatorKeyRegistered(bytes pubKey, uint256 indexed, bytes32 indexed); event SuccessfullyProvisioned(bytes pubKey, uint256 indexed, bytes32 indexed); event ModuleWeightsChanged(bytes32[] oldWeights, bytes32[] newWeights); @@ -31,6 +31,8 @@ contract PufferProtocolTest is UnitTestHelper { bytes32 constant CRAZY_GAINS = bytes32("CRAZY_GAINS"); bytes32 constant DEFAULT_DEPOSIT_ROOT = bytes32("depositRoot"); + uint256 constant BOND = 2 ether; + Permit emptyPermit; // 0.01 % @@ -190,7 +192,7 @@ contract PufferProtocolTest is UnitTestHelper { assertEq( validatorTicket.balanceOf(address(pufferProtocol)), - ((amount - 1 ether) * 1 ether) / vtPrice, + ((amount - BOND) * 1 ether) / vtPrice, "VT after for pufferProtocol" ); } @@ -226,7 +228,7 @@ contract PufferProtocolTest is UnitTestHelper { // Set validator limit and try registering that many validators function test_fuzz_register_many_validators(uint8 numberOfValidatorsToProvision) external { for (uint256 i = 0; i < uint256(numberOfValidatorsToProvision); ++i) { - vm.deal(address(this), 2 ether); + vm.deal(address(this), 3 ether); _registerValidatorKey(bytes32(i), PUFFER_MODULE_0); } } @@ -249,12 +251,11 @@ contract PufferProtocolTest is UnitTestHelper { signature: new bytes(0), depositDataRoot: bytes32(""), blsEncryptedPrivKeyShares: new bytes[](3), - blsPubKeySet: new bytes(48), - raveEvidence: new bytes(0) // No rave + blsPubKeySet: new bytes(48) }); vm.expectEmit(true, true, true, true); - emit ValidatorKeyRegistered(pubKey, 0, PUFFER_MODULE_0, false); + emit ValidatorKeyRegistered(pubKey, 0, PUFFER_MODULE_0); pufferProtocol.registerValidatorKey{ value: vtPrice + 2 ether }( validatorData, PUFFER_MODULE_0, emptyPermit, emptyPermit ); @@ -276,8 +277,7 @@ contract PufferProtocolTest is UnitTestHelper { signature: new bytes(0), depositDataRoot: bytes32(""), blsEncryptedPrivKeyShares: new bytes[](3), - blsPubKeySet: new bytes(144), - raveEvidence: new bytes(1) + blsPubKeySet: new bytes(144) }); vm.expectRevert(IPufferProtocol.InvalidBLSPubKey.selector); @@ -287,7 +287,7 @@ contract PufferProtocolTest is UnitTestHelper { } function test_get_payload() public view { - (bytes[] memory guardianPubKeys,, uint256 threshold,) = pufferProtocol.getPayload(PUFFER_MODULE_0, false); + (bytes[] memory guardianPubKeys,, uint256 threshold,) = pufferProtocol.getPayload(PUFFER_MODULE_0); assertEq(guardianPubKeys[0], guardian1EnclavePubKey, "guardian1"); assertEq(guardianPubKeys[1], guardian2EnclavePubKey, "guardian2"); @@ -539,16 +539,16 @@ contract PufferProtocolTest is UnitTestHelper { uint256 expectedMint = pufferVault.previewDeposit(1 ether); assertGt(expectedMint, 0, "should expect more pufETH"); - // Alice mints 1 ETH of pufETH + // Alice mints 2 ETH of pufETH vm.startPrank(alice); - uint256 minted = pufferVault.depositETH{ value: 1 ether }(alice); + uint256 minted = pufferVault.depositETH{ value: 2 ether }(alice); assertGt(minted, 0, "should mint pufETH"); // approve pufETH to pufferProtocol pufferVault.approve(address(pufferProtocol), type(uint256).max); assertEq(pufferVault.balanceOf(address(pufferProtocol)), 0, "zero pufETH before"); - assertEq(pufferVault.balanceOf(alice), 1 ether, "1 pufETH before for alice"); + assertEq(pufferVault.balanceOf(alice), 2 ether, "2 pufETH before for alice"); // In this case, the only important data on permit is the amount // Permit call will fail, but the amount is reused @@ -561,14 +561,14 @@ contract PufferProtocolTest is UnitTestHelper { // Register validator key by paying SC in ETH and depositing bond in pufETH vm.expectEmit(true, true, true, true); - emit ValidatorKeyRegistered(pubKey, 0, PUFFER_MODULE_0, true); + emit ValidatorKeyRegistered(pubKey, 0, PUFFER_MODULE_0); pufferProtocol.registerValidatorKey{ value: sc }(data, PUFFER_MODULE_0, permit, emptyPermit); // Alice has some dust in her wallet, because VT purchase changes the exchange rate, meaning pufETH is worth more - assertEq(pufferVault.balanceOf(alice), 1696417975049392, "1696417975049392 pufETH after for alice"); + assertEq(pufferVault.balanceOf(alice), 3389455624732864, "3389455624732864 pufETH after for alice"); uint256 protocolPufETHBalance = pufferVault.balanceOf(address(pufferProtocol)); - assertApproxEqRel(protocolPufETHBalance, 0.998303582024950608 ether, pointZeroZeroTwo, "~0.998 pufETH after"); + assertApproxEqRel(protocolPufETHBalance, 1.996607164 ether, pointZeroZeroTwo, "~1.996 pufETH after"); assertApproxEqRel( - pufferVault.convertToAssets(protocolPufETHBalance), 1 ether, pointZeroZeroOne, "1 ETH worth of pufETH after" + pufferVault.convertToAssets(protocolPufETHBalance), 2 ether, pointZeroZeroOne, "2 ETH worth of pufETH after" ); } @@ -577,12 +577,12 @@ contract PufferProtocolTest is UnitTestHelper { bytes memory pubKey = _getPubKey(bytes32("alice")); vm.deal(alice, 10 ether); - // Alice mints 1 ETH of pufETH + // Alice mints 2 ETH of pufETH vm.startPrank(alice); - pufferVault.depositETH{ value: 1 ether }(alice); + pufferVault.depositETH{ value: 2 ether }(alice); assertEq(pufferVault.balanceOf(address(pufferProtocol)), 0, "zero pufETH before"); - assertEq(pufferVault.balanceOf(alice), 1 ether, "1 pufETH before for alice"); + assertEq(pufferVault.balanceOf(alice), 2 ether, "2 pufETH before for alice"); ValidatorKeyData memory data = _getMockValidatorKeyData(pubKey, PUFFER_MODULE_0); // Generate Permit data for 2 pufETH to the protocol @@ -596,16 +596,16 @@ contract PufferProtocolTest is UnitTestHelper { // Register validator key by paying SC in ETH and depositing bond in pufETH vm.expectEmit(true, true, true, true); - emit ValidatorKeyRegistered(pubKey, 0, PUFFER_MODULE_0, true); + emit ValidatorKeyRegistered(pubKey, 0, PUFFER_MODULE_0); pufferProtocol.registerValidatorKey{ value: sc }(data, PUFFER_MODULE_0, permit, emptyPermit); // Alice has some dust in her wallet, because VT purchase changes the exchange rate, meaning pufETH is worth more - assertEq(pufferVault.balanceOf(alice), 1696417975049392, "1696417975049392 pufETH after for alice"); + assertEq(pufferVault.balanceOf(alice), 3389455624732864, "3389455624732864 pufETH after for alice"); uint256 protocolPufETHBalance = pufferVault.balanceOf(address(pufferProtocol)); - assertEq(protocolPufETHBalance, 0.998303582024950608 ether, "~0.99 pufETH after"); + assertApproxEqRel(protocolPufETHBalance, 1.996610544 ether, pointZeroZeroOne, "~1.996 pufETH after"); assertApproxEqRel( - pufferVault.convertToAssets(protocolPufETHBalance), 1 ether, pointZeroZeroOne, "1 ETH worth of pufETH after" + pufferVault.convertToAssets(protocolPufETHBalance), 2 ether, pointZeroZeroOne, "2 ETH worth of pufETH after" ); } @@ -617,26 +617,25 @@ contract PufferProtocolTest is UnitTestHelper { uint256 numberOfDays = 200; uint256 amount = pufferOracle.getValidatorTicketPrice() * numberOfDays; - // Alice mints 1 ETH of pufETH + // Alice mints 2 ETH of pufETH vm.startPrank(alice); // Purchase pufETH - pufferVault.depositETH{ value: 1 ether }(alice); + pufferVault.depositETH{ value: 2 ether }(alice); // Alice purchases VT validatorTicket.purchaseValidatorTicket{ value: amount }(alice); // Because Alice purchased a lot of VT's, it changed the conversion rate // Because of that the registerValidatorKey will .transferFrom a smaller amount of pufETH - uint256 leftOverPufETH = pufferVault.balanceOf(alice) - pufferVault.convertToShares(1 ether); + uint256 leftOverPufETH = pufferVault.balanceOf(alice) - pufferVault.convertToShares(2 ether); assertEq(pufferVault.balanceOf(address(pufferProtocol)), 0, "zero pufETH before"); - assertEq(pufferVault.balanceOf(alice), 1 ether, "1 pufETH before for alice"); + assertEq(pufferVault.balanceOf(alice), 2 ether, "2 pufETH before for alice"); assertEq(validatorTicket.balanceOf(alice), _upscaleTo18Decimals(numberOfDays), "VT before for alice"); ValidatorKeyData memory data = _getMockValidatorKeyData(pubKey, PUFFER_MODULE_0); - uint256 bond = 1 ether; Permit memory pufETHPermit = _signPermit( - _testTemps("alice", address(pufferProtocol), bond, block.timestamp), pufferVault.DOMAIN_SEPARATOR() + _testTemps("alice", address(pufferProtocol), BOND, block.timestamp), pufferVault.DOMAIN_SEPARATOR() ); Permit memory vtPermit = _signPermit( _testTemps("alice", address(pufferProtocol), _upscaleTo18Decimals(numberOfDays), block.timestamp), @@ -644,12 +643,12 @@ contract PufferProtocolTest is UnitTestHelper { ); vm.expectEmit(true, true, true, true); - emit ValidatorKeyRegistered(pubKey, 0, PUFFER_MODULE_0, true); + emit ValidatorKeyRegistered(pubKey, 0, PUFFER_MODULE_0); pufferProtocol.registerValidatorKey(data, PUFFER_MODULE_0, pufETHPermit, vtPermit); assertEq(pufferVault.balanceOf(alice), leftOverPufETH, "alice should have some leftover pufETH"); assertEq(validatorTicket.balanceOf(alice), 0, "0 vt after for alice"); - assertApproxEqRel(pufferVault.balanceOf(address(pufferProtocol)), bond, 0.002e18, "1 pufETH after"); + assertApproxEqRel(pufferVault.balanceOf(address(pufferProtocol)), BOND, 0.002e18, "2 pufETH after"); } // Node operator can deposit both VT and pufETH with .approve @@ -663,20 +662,18 @@ contract PufferProtocolTest is UnitTestHelper { vm.startPrank(alice); // Alice purchases VT validatorTicket.purchaseValidatorTicket{ value: amount }(alice); - // Alice mints 1 ETH of pufETH - pufferVault.depositETH{ value: 1 ether }(alice); + // Alice mints 2 ETH of pufETH + pufferVault.depositETH{ value: 2 ether }(alice); assertEq(pufferVault.balanceOf(address(pufferProtocol)), 0, "zero pufETH before"); // 1 wei diff assertApproxEqAbs( - pufferVault.convertToAssets(pufferVault.balanceOf(alice)), 1 ether, 1, "1 pufETH before for alice" + pufferVault.convertToAssets(pufferVault.balanceOf(alice)), 2 ether, 1, "2 pufETH before for alice" ); assertEq(validatorTicket.balanceOf(alice), _upscaleTo18Decimals(numberOfDays), "VT before for alice"); ValidatorKeyData memory data = _getMockValidatorKeyData(pubKey, PUFFER_MODULE_0); - uint256 bond = 1 ether; - pufferVault.approve(address(pufferProtocol), type(uint256).max); validatorTicket.approve(address(pufferProtocol), type(uint256).max); @@ -684,17 +681,17 @@ contract PufferProtocolTest is UnitTestHelper { vtPermit.amount = _upscaleTo18Decimals(numberOfDays); // upscale to 18 decimals Permit memory pufETHPermit = emptyPermit; - pufETHPermit.amount = pufferVault.convertToShares(bond); + pufETHPermit.amount = pufferVault.convertToShares(BOND); vm.expectEmit(true, true, true, true); - emit ValidatorKeyRegistered(pubKey, 0, PUFFER_MODULE_0, true); + emit ValidatorKeyRegistered(pubKey, 0, PUFFER_MODULE_0); pufferProtocol.registerValidatorKey(data, PUFFER_MODULE_0, pufETHPermit, vtPermit); assertEq(pufferVault.balanceOf(alice), 0, "0 pufETH after for alice"); assertEq(validatorTicket.balanceOf(alice), 0, "0 vt after for alice"); // 1 wei diff assertApproxEqAbs( - pufferVault.convertToAssets(pufferVault.balanceOf(address(pufferProtocol))), bond, 1, "1 pufETH after" + pufferVault.convertToAssets(pufferVault.balanceOf(address(pufferProtocol))), BOND, 1, "2 pufETH after" ); } @@ -720,15 +717,12 @@ contract PufferProtocolTest is UnitTestHelper { validatorTicket.DOMAIN_SEPARATOR() ); - // Alice is using SGX - uint256 bond = 1 ether; - vm.expectEmit(true, true, true, true); - emit ValidatorKeyRegistered(pubKey, 0, PUFFER_MODULE_0, true); - pufferProtocol.registerValidatorKey{ value: bond }(data, PUFFER_MODULE_0, emptyPermit, permit); + emit ValidatorKeyRegistered(pubKey, 0, PUFFER_MODULE_0); + pufferProtocol.registerValidatorKey{ value: BOND }(data, PUFFER_MODULE_0, emptyPermit, permit); assertEq(pufferVault.balanceOf(alice), 0, "0 pufETH after for alice"); - assertApproxEqRel(pufferVault.balanceOf(address(pufferProtocol)), 1 ether, pointZeroFive, "~1 pufETH after"); + assertApproxEqRel(pufferVault.balanceOf(address(pufferProtocol)), BOND, pointZeroFive, "~2 pufETH after"); } // Node operator can deposit Bond in pufETH @@ -780,10 +774,9 @@ contract PufferProtocolTest is UnitTestHelper { uint256 smoothingCommitment = pufferOracle.getValidatorTicketPrice(); bytes memory pubKey = _getPubKey(bytes32("bob")); ValidatorKeyData memory validatorKeyData = _getMockValidatorKeyData(pubKey, PUFFER_MODULE_0); - uint256 bond = 1 ether; vm.expectRevert(IPufferProtocol.ValidatorLimitForModuleReached.selector); - pufferProtocol.registerValidatorKey{ value: (smoothingCommitment + bond) }( + pufferProtocol.registerValidatorKey{ value: (smoothingCommitment + BOND) }( validatorKeyData, PUFFER_MODULE_0, emptyPermit, emptyPermit ); } @@ -792,7 +785,7 @@ contract PufferProtocolTest is UnitTestHelper { uint256 startTimestamp = 1707411226; // Alice registers one validator and we provision it - vm.deal(alice, 2 ether); + vm.deal(alice, 3 ether); vm.deal(NoRestakingModule, 200 ether); vm.startPrank(alice); @@ -801,13 +794,13 @@ contract PufferProtocolTest is UnitTestHelper { assertApproxEqAbs( pufferVault.convertToAssets(pufferVault.balanceOf(address(pufferProtocol))), - 1 ether, + BOND, 1, - "~1 pufETH in protocol" + "~2 pufETH in protocol" ); // bond + something for the validator registration - assertEq(address(pufferVault).balance, 1001.2835 ether, "vault eth balance"); + assertEq(address(pufferVault).balance, 1002.2835 ether, "vault eth balance"); Validator memory validator = pufferProtocol.getValidatorInfo(PUFFER_MODULE_0, 0); @@ -842,7 +835,7 @@ contract PufferProtocolTest is UnitTestHelper { assertEq(pufferVault.balanceOf(alice), validator.bond, "alice got the pufETH"); // 1 wei diff assertApproxEqAbs( - pufferVault.convertToAssets(pufferVault.balanceOf(alice)), 1 ether, 1, "assets owned by alice" + pufferVault.convertToAssets(pufferVault.balanceOf(alice)), 2 ether, 1, "assets owned by alice" ); // Alice doesn't withdraw her VT's right away @@ -1122,7 +1115,7 @@ contract PufferProtocolTest is UnitTestHelper { assertEq(validatorTicket.balanceOf(address(pufferProtocol)), 30 ether, "protocol has 30 VT"); assertApproxEqAbs( - _getUnderlyingETHAmount(address(pufferProtocol)), 1 ether, 1, "protocol should have ~1 eth bond" + _getUnderlyingETHAmount(address(pufferProtocol)), BOND, 1, "protocol should have ~2 eth bond" ); vm.startPrank(alice); @@ -1152,7 +1145,7 @@ contract PufferProtocolTest is UnitTestHelper { _getUnderlyingETHAmount(address(pufferProtocol)), 0 ether, 1, "protocol should have 0 eth bond" ); - assertApproxEqAbs(_getUnderlyingETHAmount(address(alice)), 1 ether, 1, "alice got back the bond"); + assertApproxEqAbs(_getUnderlyingETHAmount(address(alice)), BOND, 1, "alice got back the bond"); // We've removed the validator data, meaning the validator status is 0 (UNINITIALIZED) vm.expectRevert(abi.encodeWithSelector(IPufferProtocol.InvalidValidatorState.selector, 0)); @@ -1245,9 +1238,9 @@ contract PufferProtocolTest is UnitTestHelper { ); // Alice got more because she earned the rewards from Bob's registration - assertGe(_getUnderlyingETHAmount(address(alice)), 1 ether, "alice got back the bond gt"); + assertGe(_getUnderlyingETHAmount(address(alice)), BOND, "alice got back the bond gt"); - assertApproxEqAbs(_getUnderlyingETHAmount(address(bob)), 1 ether, 1, "bob got back the bond"); + assertApproxEqAbs(_getUnderlyingETHAmount(address(bob)), BOND, 1, "bob got back the bond"); } // Batch claim of different amounts @@ -1414,9 +1407,9 @@ contract PufferProtocolTest is UnitTestHelper { ); // Alice got more because she earned the rewards from Bob's registration - assertGe(_getUnderlyingETHAmount(address(alice)), 1 ether, "alice got back the bond gt"); + assertGe(_getUnderlyingETHAmount(address(alice)), BOND, "alice got back the bond gt"); - assertApproxEqAbs(_getUnderlyingETHAmount(address(bob)), 1 ether, 1, "bob got back the bond"); + assertApproxEqAbs(_getUnderlyingETHAmount(address(bob)), BOND, 1, "bob got back the bond"); } function test_batch_vs_multiple_single_withdrawals() public { @@ -1462,7 +1455,7 @@ contract PufferProtocolTest is UnitTestHelper { // Get the exchange rate before provisioning validators uint256 exchangeRateBefore = pufferVault.convertToShares(1 ether); - assertEq(exchangeRateBefore, 999433604122689216, "shares before provisioning"); + assertEq(exchangeRateBefore, 999433886374375918, "shares before provisioning"); uint256 startTimestamp = 1707411226; vm.warp(startTimestamp); @@ -1493,13 +1486,13 @@ contract PufferProtocolTest is UnitTestHelper { // 1 ETH gives you more pufETH after the `retrieveBond` call, meaning it is worse than before assertLt(exchangeRateBefore, pufferVault.convertToShares(1 ether), "shares after retrieve"); - // The other validator has less than 1 ETH in the bond + // The other validator has less than 2 ETH in the bond // Bad dept is shared between all pufETH holders assertApproxEqRel( pufferVault.balanceOf(address(pufferProtocol)), - 1 ether, + 2 ether, pointZeroOne, - "1 ETH worth of pufETH in the protocol" + "2 ETH worth of pufETH in the protocol" ); assertEq(pufferVault.balanceOf(alice), 0, "0 pufETH alice"); } @@ -1516,7 +1509,7 @@ contract PufferProtocolTest is UnitTestHelper { // Get the exchange rate before provisioning validators uint256 exchangeRateBefore = pufferVault.convertToShares(1 ether); - assertEq(exchangeRateBefore, 999433604122689216, "shares before provisioning"); + assertEq(exchangeRateBefore, 999433886374375918, "shares before provisioning"); uint256 startTimestamp = 1707411226; vm.warp(startTimestamp); @@ -1535,7 +1528,7 @@ contract PufferProtocolTest is UnitTestHelper { pufferModuleIndex: 0, startEpoch: 100, endEpoch: _getEpochNumber(28 days, 100), - withdrawalAmount: 30.5 ether, + withdrawalAmount: 29.5 ether, wasSlashed: true }); @@ -1549,14 +1542,14 @@ contract PufferProtocolTest is UnitTestHelper { // Bad dept is shared between all pufETH holders assertApproxEqRel( pufferVault.convertToAssets(pufferVault.balanceOf(address(pufferProtocol))), - 1 ether, + 2 ether, pointZeroOne, - "1 ether ETH worth of pufETH in the protocol" + "2 ether ETH worth of pufETH in the protocol" ); assertEq(pufferVault.balanceOf(alice), 0, "0 pufETH alice"); } - // Register 2 validators, provision 1, slash 1 whole validator bond (1 ETH) + // Register 2 validators, provision 1, slash 1 whole validator bond (2 ETH) // Case 3 function test_slashing_case_3() public { vm.deal(alice, 10 ether); @@ -1568,7 +1561,7 @@ contract PufferProtocolTest is UnitTestHelper { // Get the exchange rate before provisioning validators uint256 exchangeRateBefore = pufferVault.convertToShares(1 ether); - assertEq(exchangeRateBefore, 999433604122689216, "shares before provisioning"); + assertEq(exchangeRateBefore, 999433886374375918, "shares before provisioning"); uint256 startTimestamp = 1707411226; vm.warp(startTimestamp); @@ -1587,7 +1580,7 @@ contract PufferProtocolTest is UnitTestHelper { pufferModuleIndex: 0, startEpoch: 100, endEpoch: _getEpochNumber(28 days, 100), - withdrawalAmount: 31 ether, + withdrawalAmount: 30 ether, wasSlashed: true }); @@ -1601,17 +1594,17 @@ contract PufferProtocolTest is UnitTestHelper { // 1 ETH gives you less pufETH after the `retrieveBond` call, meaning it is better than before (slightly) assertGt(exchangeRateBefore, pufferVault.convertToShares(1 ether), "shares after retrieve"); - // Alice has a little over 1 ETH because she earned something for paying the VT on the second validator registration + // Alice has a little over 2 ETH because she earned something for paying the VT on the second validator registration assertApproxEqRel( pufferVault.convertToAssets(pufferVault.balanceOf(address(pufferProtocol))), - 1 ether, + 2 ether, pointZeroZeroOne, - "1 ETH worth of pufETH in the protocol" + "2 ETH worth of pufETH in the protocol" ); assertGt( pufferVault.convertToAssets(pufferVault.balanceOf(address(pufferProtocol))), - 1 ether, - "1 ETH worth of pufETH in the protocol gt" + 2 ether, + "2 ETH worth of pufETH in the protocol gt" ); assertEq(pufferVault.balanceOf(alice), 0, "0 pufETH alice"); } @@ -1628,7 +1621,7 @@ contract PufferProtocolTest is UnitTestHelper { // Get the exchange rate before provisioning validators uint256 exchangeRateBefore = pufferVault.convertToShares(1 ether); - assertEq(exchangeRateBefore, 999433604122689216, "shares before provisioning"); + assertEq(exchangeRateBefore, 999433886374375918, "shares before provisioning"); uint256 startTimestamp = 1707411226; vm.warp(startTimestamp); @@ -1657,12 +1650,12 @@ contract PufferProtocolTest is UnitTestHelper { // Exchange rate stays the same assertEq(exchangeRateBefore, pufferVault.convertToShares(1 ether), "shares after retrieve"); - // Alice has ~ 1 ETH locked in the protocol + // Alice has ~ 2 ETH locked in the protocol assertApproxEqRel( pufferVault.convertToAssets(pufferVault.balanceOf(address(pufferProtocol))), - 1 ether, + 2 ether, pointZeroZeroOne, - "1 ETH worth of pufETH in the protocol" + "2 ETH worth of pufETH in the protocol" ); // Alice got a little over 0.9 ETH worth of pufETH because she earned something for paying the VT on the second validator registration assertGt(pufferVault.convertToAssets(pufferVault.balanceOf(alice)), 0.9 ether, ">0.9 ETH worth of pufETH alice"); @@ -1680,7 +1673,7 @@ contract PufferProtocolTest is UnitTestHelper { // Get the exchange rate before provisioning validators uint256 exchangeRateBefore = pufferVault.convertToShares(1 ether); - assertEq(exchangeRateBefore, 999433604122689216, "shares before provisioning"); + assertEq(exchangeRateBefore, 999433886374375918, "shares before provisioning"); uint256 startTimestamp = 1707411226; vm.warp(startTimestamp); @@ -1712,12 +1705,12 @@ contract PufferProtocolTest is UnitTestHelper { // Alice has ~ 1 ETH locked in the protocol assertApproxEqRel( pufferVault.convertToAssets(pufferVault.balanceOf(address(pufferProtocol))), - 1 ether, + 2 ether, pointZeroZeroOne, - "1 ETH worth of pufETH in the protocol" + "2 ETH worth of pufETH in the protocol" ); - // Alice got a little over 1 ETH worth of pufETH because she earned something for paying the VT on the second validator registration - assertGt(pufferVault.convertToAssets(pufferVault.balanceOf(alice)), 1 ether, ">1 ETH worth of pufETH alice"); + // Alice got a little over 2 ETH worth of pufETH because she earned something for paying the VT on the second validator registration + assertGt(pufferVault.convertToAssets(pufferVault.balanceOf(alice)), 2 ether, ">2 ETH worth of pufETH alice"); } function test_validator_early_exit_dos() public { @@ -1784,29 +1777,29 @@ contract PufferProtocolTest is UnitTestHelper { // User purchases a lot of VT using ETH, but uses Permit to transfer pufETH function test_purchase_big_amount_of_vt() public { bytes memory pubKey = _getPubKey(bytes32("alice")); - vm.deal(alice, 10 ether); + vm.deal(alice, 11 ether); - // Alice mints 1 ETH of pufETH + // Alice mints 2 ETH of pufETH vm.startPrank(alice); - pufferVault.depositETH{ value: 1 ether }(alice); + pufferVault.depositETH{ value: 2 ether }(alice); assertEq(pufferVault.balanceOf(address(pufferProtocol)), 0, "zero pufETH before"); - assertEq(pufferVault.balanceOf(alice), 1 ether, "1 pufETH before for alice"); + assertEq(pufferVault.balanceOf(alice), 2 ether, "2 pufETH before for alice"); ValidatorKeyData memory data = _getMockValidatorKeyData(pubKey, PUFFER_MODULE_0); - // Generate Permit data for 1 pufETH to the protocol + // Generate Permit data for 2 pufETH to the protocol Permit memory permit = _signPermit( - _testTemps("alice", address(pufferProtocol), 1 ether, block.timestamp), pufferVault.DOMAIN_SEPARATOR() + _testTemps("alice", address(pufferProtocol), 2 ether, block.timestamp), pufferVault.DOMAIN_SEPARATOR() ); // Register validator key by paying SC in ETH and depositing bond in pufETH vm.expectEmit(true, true, true, true); - emit ValidatorKeyRegistered(pubKey, 0, PUFFER_MODULE_0, true); + emit ValidatorKeyRegistered(pubKey, 0, PUFFER_MODULE_0); pufferProtocol.registerValidatorKey{ value: 9 ether }(data, PUFFER_MODULE_0, permit, emptyPermit); // Because alice purchased VT in the registration TX, it modified the exchange rate and we take less pufETH from her. - assertEq(pufferVault.balanceOf(alice), 8424921124709635, "alice has 8424921124709635 pufETH after registering"); + assertEq(pufferVault.balanceOf(alice), 16833167574628528, "alice has 16833167574628528 pufETH after registering"); } // Alice uses Permit for VT and pays for the bond with ETH, but sends more ETH than needed @@ -1947,7 +1940,7 @@ contract PufferProtocolTest is UnitTestHelper { hex"8aa088146c8c6ca6d8ad96648f20e791be7c449ce7035a6bd0a136b8c7b7867f730428af8d4a2b69658bfdade185d6110b938d7a59e98d905e922d53432e216dc88c3384157d74200d3f2de51d31737ce19098ff4d4f54f77f0175e23ac98da5"; } - // Generates a mock validator data for SGX 1 ETH case + // Generates a mock validator data for 2 ETH case function _getMockValidatorKeyData(bytes memory pubKey, bytes32 moduleName) internal view @@ -1975,8 +1968,7 @@ contract PufferProtocolTest is UnitTestHelper { withdrawalCredentials: withdrawalCredentials }), blsEncryptedPrivKeyShares: new bytes[](3), - blsPubKeySet: new bytes(48), - raveEvidence: bytes("mock rave") // Guardians are checking it off chain + blsPubKeySet: new bytes(48) }); return validatorData; @@ -2013,12 +2005,10 @@ contract PufferProtocolTest is UnitTestHelper { ValidatorKeyData memory validatorKeyData = _getMockValidatorKeyData(pubKey, moduleName); uint256 idx = pufferProtocol.getPendingValidatorIndex(moduleName); - uint256 bond = 1 ether; - // Empty permit means that the node operator is paying with ETH for both bond & VT in the registration transaction vm.expectEmit(true, true, true, true); - emit ValidatorKeyRegistered(pubKey, idx, moduleName, true); - pufferProtocol.registerValidatorKey{ value: (vtPrice + bond) }( + emit ValidatorKeyRegistered(pubKey, idx, moduleName); + pufferProtocol.registerValidatorKey{ value: (vtPrice + BOND) }( validatorKeyData, moduleName, emptyPermit, emptyPermit ); } From 118b57e329f4a017d3a69bcd94a38b33fedafe45 Mon Sep 17 00:00:00 2001 From: eladiosch <3090613+eladiosch@users.noreply.github.com> Date: Tue, 10 Mar 2026 17:08:04 +0000 Subject: [PATCH 42/51] forge fmt --- mainnet-contracts/src/PufferProtocol.sol | 6 +----- mainnet-contracts/src/interface/IPufferProtocol.sol | 4 +--- mainnet-contracts/src/struct/ValidatorKeyData.sol | 2 +- .../test/handlers/PufferProtocolHandler.sol | 2 +- mainnet-contracts/test/unit/PufferProtocol.t.sol | 12 ++++++------ 5 files changed, 10 insertions(+), 16 deletions(-) diff --git a/mainnet-contracts/src/PufferProtocol.sol b/mainnet-contracts/src/PufferProtocol.sol index dbb6e391..fcd8c15b 100644 --- a/mainnet-contracts/src/PufferProtocol.sol +++ b/mainnet-contracts/src/PufferProtocol.sol @@ -604,11 +604,7 @@ contract PufferProtocol is IPufferProtocol, AccessManagedUpgradeable, UUPSUpgrad /** * @notice Returns necessary information to make Guardian's life easier */ - function getPayload(bytes32 moduleName) - external - view - returns (bytes[] memory, bytes memory, uint256, uint256) - { + function getPayload(bytes32 moduleName) external view returns (bytes[] memory, bytes memory, uint256, uint256) { ProtocolStorage storage $ = _getPufferProtocolStorage(); bytes[] memory pubKeys = GUARDIAN_MODULE.getGuardiansEnclavePubkeys(); diff --git a/mainnet-contracts/src/interface/IPufferProtocol.sol b/mainnet-contracts/src/interface/IPufferProtocol.sol index d381ab2e..c2f019f0 100644 --- a/mainnet-contracts/src/interface/IPufferProtocol.sol +++ b/mainnet-contracts/src/interface/IPufferProtocol.sol @@ -147,9 +147,7 @@ interface IPufferProtocol { * @param moduleName is the staking Module * @dev Signature "0x6b9febc68231d6c196b22b02f442fa6dc3148ee90b6e83d5b978c11833587159" */ - event ValidatorKeyRegistered( - bytes pubKey, uint256 indexed pufferModuleIndex, bytes32 indexed moduleName - ); + event ValidatorKeyRegistered(bytes pubKey, uint256 indexed pufferModuleIndex, bytes32 indexed moduleName); /** * @notice Emitted when the Validator exited and stopped validating diff --git a/mainnet-contracts/src/struct/ValidatorKeyData.sol b/mainnet-contracts/src/struct/ValidatorKeyData.sol index 49380cd4..cad91953 100644 --- a/mainnet-contracts/src/struct/ValidatorKeyData.sol +++ b/mainnet-contracts/src/struct/ValidatorKeyData.sol @@ -10,4 +10,4 @@ struct ValidatorKeyData { bytes32 depositDataRoot; bytes[] blsEncryptedPrivKeyShares; bytes blsPubKeySet; -} \ No newline at end of file +} diff --git a/mainnet-contracts/test/handlers/PufferProtocolHandler.sol b/mainnet-contracts/test/handlers/PufferProtocolHandler.sol index c0d30679..c98503c5 100644 --- a/mainnet-contracts/test/handlers/PufferProtocolHandler.sol +++ b/mainnet-contracts/test/handlers/PufferProtocolHandler.sol @@ -553,7 +553,7 @@ contract PufferProtocolHandler is Test { }), blsEncryptedPrivKeyShares: new bytes[](3), blsPubKeySet: new bytes(48) - }); + }); return validatorData; } diff --git a/mainnet-contracts/test/unit/PufferProtocol.t.sol b/mainnet-contracts/test/unit/PufferProtocol.t.sol index 922937e9..da9884e9 100644 --- a/mainnet-contracts/test/unit/PufferProtocol.t.sol +++ b/mainnet-contracts/test/unit/PufferProtocol.t.sol @@ -252,7 +252,7 @@ contract PufferProtocolTest is UnitTestHelper { depositDataRoot: bytes32(""), blsEncryptedPrivKeyShares: new bytes[](3), blsPubKeySet: new bytes(48) - }); + }); vm.expectEmit(true, true, true, true); emit ValidatorKeyRegistered(pubKey, 0, PUFFER_MODULE_0); @@ -1114,9 +1114,7 @@ contract PufferProtocolTest is UnitTestHelper { _registerAndProvisionNode(bytes32("alice"), PUFFER_MODULE_0, alice); assertEq(validatorTicket.balanceOf(address(pufferProtocol)), 30 ether, "protocol has 30 VT"); - assertApproxEqAbs( - _getUnderlyingETHAmount(address(pufferProtocol)), BOND, 1, "protocol should have ~2 eth bond" - ); + assertApproxEqAbs(_getUnderlyingETHAmount(address(pufferProtocol)), BOND, 1, "protocol should have ~2 eth bond"); vm.startPrank(alice); @@ -1799,7 +1797,9 @@ contract PufferProtocolTest is UnitTestHelper { pufferProtocol.registerValidatorKey{ value: 9 ether }(data, PUFFER_MODULE_0, permit, emptyPermit); // Because alice purchased VT in the registration TX, it modified the exchange rate and we take less pufETH from her. - assertEq(pufferVault.balanceOf(alice), 16833167574628528, "alice has 16833167574628528 pufETH after registering"); + assertEq( + pufferVault.balanceOf(alice), 16833167574628528, "alice has 16833167574628528 pufETH after registering" + ); } // Alice uses Permit for VT and pays for the bond with ETH, but sends more ETH than needed @@ -1969,7 +1969,7 @@ contract PufferProtocolTest is UnitTestHelper { }), blsEncryptedPrivKeyShares: new bytes[](3), blsPubKeySet: new bytes(48) - }); + }); return validatorData; } From 3622dda3c8540506e390bef9292d4e97eaf4b9a7 Mon Sep 17 00:00:00 2001 From: Eladio Date: Fri, 13 Mar 2026 18:02:35 +0100 Subject: [PATCH 43/51] Fixed remaining tests and scripts --- mainnet-contracts/package.json | 112 +++++++++--------- mainnet-contracts/script/DeployerHelper.s.sol | 2 + ...fferModuleManagerSlasher.integration.t.sol | 6 +- .../test/handlers/PufferProtocolHandler.sol | 2 +- 4 files changed, 62 insertions(+), 60 deletions(-) diff --git a/mainnet-contracts/package.json b/mainnet-contracts/package.json index 1358b40f..433ca033 100644 --- a/mainnet-contracts/package.json +++ b/mainnet-contracts/package.json @@ -1,58 +1,58 @@ { - "name": "mainnet-contracts", - "description": "", - "version": "1.0.0", - "author": { - "name": "Puffer Finance", - "url": "https://puffer.fi" - }, - "dependencies": { - "@layerzerolabs/lz-evm-messagelib-v2": "^3.0.75", - "@layerzerolabs/lz-evm-protocol-v2": "^3.0.75", - "@layerzerolabs/lz-evm-v1-0.7": "^3.0.75", - "@layerzerolabs/oapp-evm": "^0.3.2", - "@layerzerolabs/oft-evm": "^3.1.3", - "@openzeppelin/contracts": "5.0.1", - "@openzeppelin/contracts-upgradeable": "5.0.1", - "l2-contracts": "*", - "murky": "https://github.com/dmfxyz/murky.git", - "solidity-bytes-utils": "^0.8.4", - "solidity-stringutils": "https://github.com/Arachnid/solidity-stringutils" - }, - "devDependencies": { - "@crytic/properties": "https://github.com/crytic/properties#f1ff61b", - "@layerzerolabs/test-devtools-evm-foundry": "^6.0.3", - "@prb/test": "0.6.4", - "erc4626-tests": "https://github.com/a16z/erc4626-tests#232ff9b", - "forge-std": "github:foundry-rs/forge-std#v1.9.6", - "partners-layerzero": "*", - "solarray": "github:evmcheb/solarray#a547630", - "solhint": "^5.0.3" - }, - "homepage": "https://puffer.fi", - "keywords": [ - "blockchain", - "foundry", - "smart-contracts", - "solidity", - "web3", - "ethereum", - "puffer", - "puffer-finance", - "solidity", - "LRT", - "eigenlayer", - "restaking", - "liquid-staking" - ], - "scripts": { - "fmt": "forge fmt", - "build": "forge build", - "gas": "forge test --gas-report --mp \"./test/unit/**/*.sol\"", - "lint": "yarn run lint:sol", - "test:unit": "forge test --mp \"./test/unit/**/*.sol\" -vvv", - "slither": "slither .", - "coverage": "forge coverage --force --no-match-coverage \"(script|test|mock|interface|node_modules|echidna)\" --no-match-contract \"PufferModuleManagerHoleskyTestnetFFI\"", - "coverage-lcov": "forge coverage --force --no-match-coverage \"(script|test|mock|interface|node_modules|echidna)\" --no-match-contract \"PufferModuleManagerHoleskyTestnetFFI\" --report lcov" - } + "name": "mainnet-contracts", + "description": "", + "version": "1.0.0", + "author": { + "name": "Puffer Finance", + "url": "https://puffer.fi" + }, + "dependencies": { + "@layerzerolabs/lz-evm-messagelib-v2": "^3.0.75", + "@layerzerolabs/lz-evm-protocol-v2": "^3.0.75", + "@layerzerolabs/lz-evm-v1-0.7": "^3.0.75", + "@layerzerolabs/oapp-evm": "^0.3.2", + "@layerzerolabs/oft-evm": "^3.1.3", + "@openzeppelin/contracts": "5.0.1", + "@openzeppelin/contracts-upgradeable": "5.0.1", + "l2-contracts": "*", + "murky": "https://github.com/dmfxyz/murky.git", + "solidity-bytes-utils": "^0.8.4", + "solidity-stringutils": "https://github.com/Arachnid/solidity-stringutils" + }, + "devDependencies": { + "@crytic/properties": "https://github.com/crytic/properties#f1ff61b", + "@layerzerolabs/test-devtools-evm-foundry": "^6.0.3", + "@prb/test": "0.6.4", + "erc4626-tests": "https://github.com/a16z/erc4626-tests#232ff9b", + "forge-std": "github:foundry-rs/forge-std#v1.9.6", + "partners-layerzero": "*", + "solarray": "github:evmcheb/solarray#a547630", + "solhint": "^5.0.3" + }, + "homepage": "https://puffer.fi", + "keywords": [ + "blockchain", + "foundry", + "smart-contracts", + "solidity", + "web3", + "ethereum", + "puffer", + "puffer-finance", + "solidity", + "LRT", + "eigenlayer", + "restaking", + "liquid-staking" + ], + "scripts": { + "fmt": "forge fmt", + "build": "forge build", + "gas": "forge test --gas-report --mp \"./test/unit/**/*.sol\"", + "lint": "yarn run lint:sol", + "test:unit": "forge test --mp \"./test/unit/**/*.sol\" -vvv", + "slither": "slither .", + "coverage": "forge coverage --ir-minimum --force --no-match-coverage \"(script|test|mock|interface|node_modules|echidna)\" --no-match-contract \"CarrotVestingTest\"", + "coverage-lcov": "forge coverage --ir-minimum --force --no-match-coverage \"(script|test|mock|interface|node_modules|echidna)\" --no-match-contract \"CarrotVestingTest\" --report lcov" + } } diff --git a/mainnet-contracts/script/DeployerHelper.s.sol b/mainnet-contracts/script/DeployerHelper.s.sol index 513e32f5..25b3774e 100644 --- a/mainnet-contracts/script/DeployerHelper.s.sol +++ b/mainnet-contracts/script/DeployerHelper.s.sol @@ -121,6 +121,8 @@ abstract contract DeployerHelper is Script { function _getBeaconChainStrategy() internal view returns (address) { if (block.chainid == holesky) { return 0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0; + } else if (block.chainid == hoodi) { + return 0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0; } revert("BEACON_CHAIN_STRATEGY not available for this chain"); diff --git a/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol b/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol index 8e3a1bb7..3977364a 100644 --- a/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol +++ b/mainnet-contracts/test/fork-tests/PufferModuleManagerSlasher.integration.t.sol @@ -29,7 +29,7 @@ contract PufferModuleManagerSlasherIntegrationTest is Test, DeployerHelper { DeployPufferModuleImplementation deployPufferModule; DeployRestakingOperator deployRestakingOperator; - uint32 START_BLOCK = 2352200; // Mar-04-2026 05:17:12 PM +UTC + uint32 START_BLOCK = 2409477; // Mar-13-2026 12:19:00 PM +UTC function setUp() public { vm.createSelectFork(vm.rpcUrl("hoodi"), START_BLOCK); @@ -71,7 +71,7 @@ contract PufferModuleManagerSlasherIntegrationTest is Test, DeployerHelper { function test_queue_and_claim_withdrawals() public { vm.startPrank(_getPaymaster()); - uint256 amount = 0.1 ether; + uint256 amount = 0.0001 ether; pufferModuleManager.callQueueWithdrawals(PUFFER_MODULE_0_NAME, amount); IStrategy[] memory strategies = new IStrategy[](1); @@ -85,7 +85,7 @@ contract PufferModuleManagerSlasherIntegrationTest is Test, DeployerHelper { staker: PUFFER_MODULE_0_HOODI, delegatedTo: RESTAKING_OPERATOR_0_HOODI, withdrawer: PUFFER_MODULE_0_HOODI, - nonce: 42, + nonce: 0, startBlock: START_BLOCK, strategies: strategies, scaledShares: scaledShares diff --git a/mainnet-contracts/test/handlers/PufferProtocolHandler.sol b/mainnet-contracts/test/handlers/PufferProtocolHandler.sol index c98503c5..2b14f86d 100644 --- a/mainnet-contracts/test/handlers/PufferProtocolHandler.sol +++ b/mainnet-contracts/test/handlers/PufferProtocolHandler.sol @@ -428,7 +428,7 @@ contract PufferProtocolHandler is Test { // Account for that deposited eth in ghost variable ghost_eth_deposited_amount += depositedETHAmount; ghost_validators += 1; - ghost_pufETH_bond_amount += pufferVault.previewDeposit(1 ether); + ghost_pufETH_bond_amount += pufferVault.previewDeposit(2 ether); // Add node operator to the set _nodeOperators.add(currentActor); From 1ca5c18c2e0bcb3ff387241b35331c7e075341f3 Mon Sep 17 00:00:00 2001 From: Eladio Date: Mon, 16 Mar 2026 12:11:23 +0100 Subject: [PATCH 44/51] Increased coverage --- .github/workflows/mainnet-contracts.yml | 2 +- .../test/unit/GuardianModule.t.sol | 36 ++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/.github/workflows/mainnet-contracts.yml b/.github/workflows/mainnet-contracts.yml index 9835a8b6..84650f47 100644 --- a/.github/workflows/mainnet-contracts.yml +++ b/.github/workflows/mainnet-contracts.yml @@ -107,7 +107,7 @@ jobs: - name: "Generate the coverage report" working-directory: mainnet-contracts - run: 'forge coverage --no-match-coverage "(script|test|mock|node_modules|interface|integrations|echidna|L1RewardManagerUnsafe)" --no-match-contract "CarrotVestingTest" --report lcov -vvv --ir-minimum' + run: 'forge coverage --no-match-coverage "(script|test|mock|node_modules|interface|integrations|echidna|L1RewardManagerUnsafe)" --no-match-contract "CarrotVestingTest" --report lcov -vvv --ir-minimum' env: ETH_RPC_URL: ${{ secrets.ETH_RPC_URL }} HOLESKY_RPC_URL: ${{ secrets.HOLESKY_RPC_URL }} diff --git a/mainnet-contracts/test/unit/GuardianModule.t.sol b/mainnet-contracts/test/unit/GuardianModule.t.sol index 9e9bdbbd..9dfe4c6a 100644 --- a/mainnet-contracts/test/unit/GuardianModule.t.sol +++ b/mainnet-contracts/test/unit/GuardianModule.t.sol @@ -3,10 +3,14 @@ pragma solidity >=0.8.0 <0.9.0; import { UnitTestHelper } from "../helpers/UnitTestHelper.sol"; import { IGuardianModule, PublicIdentity, GuardianSessionProof } from "../../src/interface/IGuardianModule.sol"; -import { Unauthorized } from "../../src/Errors.sol"; +import { GuardianModule } from "../../src/GuardianModule.sol"; +import { Unauthorized, InvalidAddress } from "../../src/Errors.sol"; import { SessionRegistryMock } from "../mocks/SessionRegistryMock.sol"; import { ALGO_ID_ES256K } from "@automata-network/automata-tee-workload-measurement/types/Constants.sol"; import { LibKey } from "@automata-network/automata-tee-workload-measurement/lib/LibKey.sol"; +import { ISessionRegistry } from + "@automata-network/automata-tee-workload-measurement/interfaces/registries/ISessionRegistry.sol"; + contract GuardianModuleTest is UnitTestHelper { uint256 public newSKEnclave; @@ -39,6 +43,29 @@ contract GuardianModuleTest is UnitTestHelper { newGuardianSessionPublicIdentity = PublicIdentity({ typeId: ALGO_ID_ES256K, key: newEnclavePubKey }); } + function test_invalid_constructor() public { + address[] memory guardians = new address[](1); + guardians[0] = guardian1; + address authority = guardianModule.authority(); + + // invalid session registry + vm.expectRevert(InvalidAddress.selector); + new GuardianModule(ISessionRegistry(address(0)), guardians, 1, authority, FRESHNESS_BLOCKS); + + // invalid authority + vm.expectRevert(InvalidAddress.selector); + new GuardianModule(ISessionRegistry(address(sessionRegistryMock)), guardians, 1, address(0), FRESHNESS_BLOCKS); + + // empty guardians + address[] memory emptyGuardians = new address[](1); + vm.expectRevert(InvalidAddress.selector); + new GuardianModule(ISessionRegistry(address(sessionRegistryMock)), emptyGuardians, 1, authority, FRESHNESS_BLOCKS); + + // invalid threshold + vm.expectRevert(abi.encodeWithSelector(IGuardianModule.InvalidThreshold.selector, 0)); + new GuardianModule(ISessionRegistry(address(sessionRegistryMock)), guardians, 0, authority, FRESHNESS_BLOCKS); + } + function test_setup() public view { assertEq(guardianModule.getEjectionThreshold(), 31.75 ether, "initial value ejection threshold (31.75)"); assertEq(guardianModule.getThreshold(), 1, "initial value threshold (1)"); @@ -48,6 +75,13 @@ contract GuardianModuleTest is UnitTestHelper { _deployContractAndSetupGuardians(); } + function test_set_ejection_threshold_reverts() public { + vm.startPrank(DAO); + + vm.expectRevert(abi.encodeWithSelector(IGuardianModule.InvalidThreshold.selector, 32.1 ether)); + guardianModule.setEjectionThreshold(32.1 ether); + } + function test_set_threshold_to_0_reverts() public { vm.startPrank(DAO); vm.expectRevert(abi.encodeWithSelector(IGuardianModule.InvalidThreshold.selector, 0)); From d6310480e13fc6949032336ff3297c157ac1b2f5 Mon Sep 17 00:00:00 2001 From: eladiosch <3090613+eladiosch@users.noreply.github.com> Date: Mon, 16 Mar 2026 11:15:58 +0000 Subject: [PATCH 45/51] forge fmt --- mainnet-contracts/test/unit/GuardianModule.t.sol | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mainnet-contracts/test/unit/GuardianModule.t.sol b/mainnet-contracts/test/unit/GuardianModule.t.sol index 9dfe4c6a..e8464d2a 100644 --- a/mainnet-contracts/test/unit/GuardianModule.t.sol +++ b/mainnet-contracts/test/unit/GuardianModule.t.sol @@ -11,7 +11,6 @@ import { LibKey } from "@automata-network/automata-tee-workload-measurement/lib/ import { ISessionRegistry } from "@automata-network/automata-tee-workload-measurement/interfaces/registries/ISessionRegistry.sol"; - contract GuardianModuleTest is UnitTestHelper { uint256 public newSKEnclave; bytes public newEnclavePubKey; @@ -59,7 +58,9 @@ contract GuardianModuleTest is UnitTestHelper { // empty guardians address[] memory emptyGuardians = new address[](1); vm.expectRevert(InvalidAddress.selector); - new GuardianModule(ISessionRegistry(address(sessionRegistryMock)), emptyGuardians, 1, authority, FRESHNESS_BLOCKS); + new GuardianModule( + ISessionRegistry(address(sessionRegistryMock)), emptyGuardians, 1, authority, FRESHNESS_BLOCKS + ); // invalid threshold vm.expectRevert(abi.encodeWithSelector(IGuardianModule.InvalidThreshold.selector, 0)); From 4e122a95575dbf56a98575c1f529511a2ea59fda Mon Sep 17 00:00:00 2001 From: Eladio Date: Thu, 26 Mar 2026 17:47:42 +0100 Subject: [PATCH 46/51] Updated _consoleLogOrUpgradeUUPS for hoodi --- mainnet-contracts/script/DeployerHelper.s.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mainnet-contracts/script/DeployerHelper.s.sol b/mainnet-contracts/script/DeployerHelper.s.sol index 25b3774e..ec1b8fea 100644 --- a/mainnet-contracts/script/DeployerHelper.s.sol +++ b/mainnet-contracts/script/DeployerHelper.s.sol @@ -64,7 +64,7 @@ abstract contract DeployerHelper is Script { vm.label(implementation, contractName); console.log("Deployed", contractName, "at", implementation); - if (block.chainid == holesky) { + if (block.chainid == holesky || block.chainid == hoodi) { AccessManager(_getAccessManager()).execute( proxyTarget, abi.encodeCall(UUPSUpgradeable.upgradeToAndCall, (address(implementation), data)) ); @@ -103,7 +103,7 @@ abstract contract DeployerHelper is Script { vm.label(implementation, contractName); console.log("Deployed", contractName, "at", implementation); - if (block.chainid == holesky) { + if (block.chainid == holesky || block.chainid == hoodi) { // @DEPRECATED AccessManager(_getAccessManager()).execute( proxyTarget, abi.encodeCall(UUPSUpgradeable.upgradeToAndCall, (address(implementation), data)) From ebd0857e3310e044b0d393664febb7684cc33904 Mon Sep 17 00:00:00 2001 From: Eladio Date: Fri, 27 Mar 2026 11:02:43 +0100 Subject: [PATCH 47/51] Modified l2 remappings --- l2-contracts/remappings.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/l2-contracts/remappings.txt b/l2-contracts/remappings.txt index 5f0695f3..8651c1e4 100644 --- a/l2-contracts/remappings.txt +++ b/l2-contracts/remappings.txt @@ -22,4 +22,5 @@ l2-contracts/=node_modules/l2-contracts/ @layerzerolabs/lz-evm-messagelib-v2/=node_modules/@layerzerolabs/lz-evm-messagelib-v2/ @layerzerolabs/lz-evm-v1-0.7/=node_modules/@layerzerolabs/lz-evm-v1-0.7/ solidity-bytes-utils/=node_modules/solidity-bytes-utils/ -partners-layerzero/=../partners/layerzero/ \ No newline at end of file +partners-layerzero/=../partners/layerzero/ +@automata-network/automata-tee-workload-measurement=lib/automata-tee-workload-measurement/src/ \ No newline at end of file From e8979666916069ccfee5564d308e9c2133150ca8 Mon Sep 17 00:00:00 2001 From: Eladio Date: Fri, 27 Mar 2026 11:20:20 +0100 Subject: [PATCH 48/51] Added recursive submodules to l2-contracts --- .github/workflows/l2-contracts.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/l2-contracts.yml b/.github/workflows/l2-contracts.yml index 8a82b039..e5753b19 100644 --- a/.github/workflows/l2-contracts.yml +++ b/.github/workflows/l2-contracts.yml @@ -19,6 +19,7 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 + submodules: recursive - name: Codespell uses: codespell-project/actions-codespell@v2.0 @@ -34,6 +35,8 @@ jobs: uses: styfle/cancel-workflow-action@0.12.1 - uses: actions/checkout@v4 + with: + submodules: recursive - uses: actions/setup-node@v4 with: cache: 'yarn' @@ -79,6 +82,8 @@ jobs: uses: styfle/cancel-workflow-action@0.12.1 - uses: actions/checkout@v4 + with: + submodules: recursive - uses: actions/setup-node@v4 with: cache: 'yarn' From 6b721b63c81bc028622bb56563fd3d897d52bbc5 Mon Sep 17 00:00:00 2001 From: Eladio Date: Fri, 27 Mar 2026 11:27:42 +0100 Subject: [PATCH 49/51] Updated remappings --- l2-contracts/remappings.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l2-contracts/remappings.txt b/l2-contracts/remappings.txt index 8651c1e4..bae23222 100644 --- a/l2-contracts/remappings.txt +++ b/l2-contracts/remappings.txt @@ -23,4 +23,4 @@ l2-contracts/=node_modules/l2-contracts/ @layerzerolabs/lz-evm-v1-0.7/=node_modules/@layerzerolabs/lz-evm-v1-0.7/ solidity-bytes-utils/=node_modules/solidity-bytes-utils/ partners-layerzero/=../partners/layerzero/ -@automata-network/automata-tee-workload-measurement=lib/automata-tee-workload-measurement/src/ \ No newline at end of file +@automata-network/automata-tee-workload-measurement=../mainnet-contracts/lib/automata-tee-workload-measurement/src/ \ No newline at end of file From de90dc4fd3b28d7a9b7ea50d200710db35757035 Mon Sep 17 00:00:00 2001 From: Eladio Date: Thu, 2 Apr 2026 12:51:31 +0200 Subject: [PATCH 50/51] Added ValidatorTicketsDeposited event to the registerValidatorKey flow --- mainnet-contracts/src/PufferProtocol.sol | 1 + mainnet-contracts/test/unit/PufferProtocol.t.sol | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/mainnet-contracts/src/PufferProtocol.sol b/mainnet-contracts/src/PufferProtocol.sol index fcd8c15b..0892b0d5 100644 --- a/mainnet-contracts/src/PufferProtocol.sol +++ b/mainnet-contracts/src/PufferProtocol.sol @@ -657,6 +657,7 @@ contract PufferProtocol is IPufferProtocol, AccessManagedUpgradeable, UUPSUpgrad } emit NumberOfRegisteredValidatorsChanged(moduleName, $.moduleLimits[moduleName].numberOfRegisteredValidators); emit ValidatorKeyRegistered(data.blsPubKey, pufferModuleIndex, moduleName); + emit ValidatorTicketsDeposited(msg.sender, msg.sender, vtAmount); } function _setValidatorLimitPerModule(bytes32 moduleName, uint128 limit) internal { diff --git a/mainnet-contracts/test/unit/PufferProtocol.t.sol b/mainnet-contracts/test/unit/PufferProtocol.t.sol index da9884e9..6ccfd4d8 100644 --- a/mainnet-contracts/test/unit/PufferProtocol.t.sol +++ b/mainnet-contracts/test/unit/PufferProtocol.t.sol @@ -16,6 +16,7 @@ import { LibGuardianMessages } from "../../src/LibGuardianMessages.sol"; import { Permit } from "../../src/structs/Permit.sol"; import { ModuleLimit } from "../../src/struct/ProtocolStorage.sol"; import { StoppedValidatorInfo } from "../../src/struct/StoppedValidatorInfo.sol"; +import { VmSafe } from "forge-std/Vm.sol"; contract PufferProtocolTest is UnitTestHelper { using ECDSA for bytes32; @@ -23,6 +24,7 @@ contract PufferProtocolTest is UnitTestHelper { event ValidatorKeyRegistered(bytes pubKey, uint256 indexed, bytes32 indexed); event SuccessfullyProvisioned(bytes pubKey, uint256 indexed, bytes32 indexed); event ModuleWeightsChanged(bytes32[] oldWeights, bytes32[] newWeights); + event ValidatorTicketsDeposited(address indexed node, address indexed depositor, uint256 amount); bytes zeroPubKey = new bytes(48); bytes32 zeroPubKeyPart; @@ -2005,9 +2007,13 @@ contract PufferProtocolTest is UnitTestHelper { ValidatorKeyData memory validatorKeyData = _getMockValidatorKeyData(pubKey, moduleName); uint256 idx = pufferProtocol.getPendingValidatorIndex(moduleName); + address msgSender = _getCaller(); + // Empty permit means that the node operator is paying with ETH for both bond & VT in the registration transaction vm.expectEmit(true, true, true, true); emit ValidatorKeyRegistered(pubKey, idx, moduleName); + vm.expectEmit(true, true, true, true); + emit ValidatorTicketsDeposited(msgSender, msgSender, numberOfDays * 1 ether); pufferProtocol.registerValidatorKey{ value: (vtPrice + BOND) }( validatorKeyData, moduleName, emptyPermit, emptyPermit ); @@ -2056,6 +2062,16 @@ contract PufferProtocolTest is UnitTestHelper { // The formula is validatedEpochs * 32 * 12 * 1 ether / 1 days (4444444444444444.44444444...) we round it up return validatedEpochs * 4444444444444445; } + + function _getCaller() internal returns (address caller) { + (VmSafe.CallerMode mode, address msgSender,) = vm.readCallers(); + + if (mode == VmSafe.CallerMode.Prank || mode == VmSafe.CallerMode.RecurrentPrank) { + return msgSender; + } else { + return address(this); + } + } } struct MerkleProofData { From 19420499b6b80b0dbd94878e33a8c43e729e9e87 Mon Sep 17 00:00:00 2001 From: Eladio Date: Fri, 3 Apr 2026 12:41:21 +0200 Subject: [PATCH 51/51] Adapted some scripts to Hoodi --- .../script/DeployPufferModuleImplementation.s.sol | 4 ++-- .../script/DeployPufferWithdrawalManager.s.sol | 2 +- mainnet-contracts/script/DeployRestakingOperator.s.sol | 6 +++--- mainnet-contracts/script/UpgradeValidatorTicket.s.sol | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mainnet-contracts/script/DeployPufferModuleImplementation.s.sol b/mainnet-contracts/script/DeployPufferModuleImplementation.s.sol index 886f9faa..8ea3165d 100644 --- a/mainnet-contracts/script/DeployPufferModuleImplementation.s.sol +++ b/mainnet-contracts/script/DeployPufferModuleImplementation.s.sol @@ -42,7 +42,7 @@ contract DeployPufferModuleImplementation is DeployerHelper { console.log("From Timelock queue a tx to accessManager"); console.logBytes(calldataToExecute); - if (block.chainid == holesky) { + if (block.chainid == holesky || block.chainid == hoodi) { AccessManager(_getAccessManager()).execute(_getPufferModuleBeacon(), cd); } } @@ -62,7 +62,7 @@ contract DeployPufferModuleImplementation is DeployerHelper { bytes memory cd = abi.encodeCall(UpgradeableBeacon.upgradeTo, address(newImpl)); - if (block.chainid == holesky) { + if (block.chainid == holesky || block.chainid == hoodi) { AccessManager(_getAccessManager()).execute(_getPufferModuleBeacon(), cd); } vm.stopPrank(); diff --git a/mainnet-contracts/script/DeployPufferWithdrawalManager.s.sol b/mainnet-contracts/script/DeployPufferWithdrawalManager.s.sol index 5f6418b5..b1ea904f 100644 --- a/mainnet-contracts/script/DeployPufferWithdrawalManager.s.sol +++ b/mainnet-contracts/script/DeployPufferWithdrawalManager.s.sol @@ -51,7 +51,7 @@ contract DeployPufferWithdrawalManager is DeployerHelper { console.log("Queue from Timelock -> AccessManager", _getAccessManager()); console.logBytes(encodedCalldata); - if (block.chainid == holesky) { + if (block.chainid == holesky || block.chainid == hoodi) { (bool success,) = address(_getAccessManager()).call(encodedCalldata); require(success, "AccessManager.call failed"); } diff --git a/mainnet-contracts/script/DeployRestakingOperator.s.sol b/mainnet-contracts/script/DeployRestakingOperator.s.sol index 87b84d99..214069f2 100644 --- a/mainnet-contracts/script/DeployRestakingOperator.s.sol +++ b/mainnet-contracts/script/DeployRestakingOperator.s.sol @@ -39,7 +39,7 @@ contract DeployRestakingOperator is DeployerHelper { console.log("From Timelock queue a tx to accessManager"); console.logBytes(calldataToExecute); - if (block.chainid == holesky) { + if (block.chainid == holesky || block.chainid == hoodi) { AccessManager(_getAccessManager()).execute(_getRestakingOperatorBeacon(), cd); } } @@ -59,7 +59,7 @@ contract DeployRestakingOperator is DeployerHelper { bytes memory cd = abi.encodeCall(UpgradeableBeacon.upgradeTo, address(restakingOperatorImplementation)); - if (block.chainid == holesky) { + if (block.chainid == holesky || block.chainid == hoodi) { AccessManager(_getAccessManager()).execute(_getRestakingOperatorBeacon(), cd); } } @@ -79,7 +79,7 @@ contract DeployRestakingOperator is DeployerHelper { bytes memory cd = abi.encodeCall(UpgradeableBeacon.upgradeTo, address(restakingOperatorImplementation)); - if (block.chainid == holesky) { + if (block.chainid == holesky || block.chainid == hoodi) { AccessManager(_getAccessManager()).execute(_getRestakingOperatorBeacon(), cd); } } diff --git a/mainnet-contracts/script/UpgradeValidatorTicket.s.sol b/mainnet-contracts/script/UpgradeValidatorTicket.s.sol index 8e3ef3ce..584af725 100644 --- a/mainnet-contracts/script/UpgradeValidatorTicket.s.sol +++ b/mainnet-contracts/script/UpgradeValidatorTicket.s.sol @@ -48,7 +48,7 @@ contract UpgradeValidatorTicket is DeployerHelper { console.logBytes(accessManagerCallData); // If on testnet, upgrade and execute access control changes directly - if (block.chainid == holesky) { + if (block.chainid == holesky || block.chainid == hoodi) { // upgrade to implementation AccessManager(_getAccessManager()).execute( address(validatorTicket),