From 5d44764e789496dcc71cd40bd599098dadc8a664 Mon Sep 17 00:00:00 2001 From: Alysia Huggins Date: Thu, 30 Jan 2025 15:33:11 -0500 Subject: [PATCH 1/5] add admin only functions --- contracts/src/StakeTable.sol | 72 +++++++++++++++-- .../src/interfaces/AbstractStakeTable.sol | 16 ++++ contracts/test/StakeTable.t.sol | 79 ++++++++++++++++++- 3 files changed, 159 insertions(+), 8 deletions(-) diff --git a/contracts/src/StakeTable.sol b/contracts/src/StakeTable.sol index 54b3a6cdc5..5e660c5196 100644 --- a/contracts/src/StakeTable.sol +++ b/contracts/src/StakeTable.sol @@ -64,6 +64,15 @@ contract StakeTable is AbstractStakeTable { // Error raised when zero point keys are provided error NoKeyChange(); + /// Error raised when the caller is not the admin + error Unauthorized(); + + /// Error raised when the light client address is invalid + error InvalidAddress(); + + /// Error raised when the value is invalid + error InvalidValue(); + /// Mapping from a hash of a BLS key to a node struct defined in the abstract contract. mapping(address account => Node node) public nodes; @@ -92,7 +101,17 @@ contract StakeTable is AbstractStakeTable { uint64 public maxChurnRate; - constructor(address _tokenAddress, address _lightClientAddress, uint64 churnRate) { + uint256 public minStakeAmount; + + address public admin; + + /// TODO change constructor to initialize function when we make the contract upgradeable + constructor( + address _tokenAddress, + address _lightClientAddress, + uint64 churnRate, + uint256 _minStakeAmount + ) { tokenAddress = _tokenAddress; lightClient = LightClient(_lightClientAddress); @@ -105,6 +124,10 @@ contract StakeTable is AbstractStakeTable { // It is not possible to exit during the first epoch. firstAvailableExitEpoch = 1; _numPendingExits = 0; + + minStakeAmount = _minStakeAmount; + + admin = msg.sender; } /// @dev Computes a hash value of some G2 point. @@ -269,7 +292,7 @@ contract StakeTable is AbstractStakeTable { BN254.G1Point memory blsSig, uint64 validUntilEpoch ) external override { - uint256 fixedStakeAmount = minStakeAmount(); + uint256 fixedStakeAmount = minStakeAmount; // Verify that the sender amount is the minStakeAmount if (amount < fixedStakeAmount) { @@ -392,6 +415,8 @@ contract StakeTable is AbstractStakeTable { /// @notice Request to exit from the stake table, not immediately withdrawable! /// /// @dev TODO modify this according to the current spec + /// @dev TODO add a function to check if the node is eligible to exit + /// @dev TODO discuss if we want an admin administered emergency exit function requestExit() external override { Node memory node = nodes[msg.sender]; @@ -524,10 +549,43 @@ contract StakeTable is AbstractStakeTable { emit UpdatedConsensusKeys(msg.sender, node.blsVK, node.schnorrVK); } - /// @notice Minimum stake amount - /// @return Minimum stake amount - /// TODO: This value should be a variable modifiable by admin - function minStakeAmount() public pure returns (uint256) { - return 10 ether; + /// @notice Update the admin + /// @dev The admin cannot be set to the zero address + /// @param _admin The new admin + function updateAdmin(address _admin) external { + if (msg.sender != admin) revert Unauthorized(); + if (_admin == address(0)) revert InvalidAddress(); + admin = _admin; + emit AdminUpdated(admin); + } + + /// @notice Update the min stake amount + /// @dev The min stake amount cannot be set to zero + /// @param _minStakeAmount The new min stake amount + function updateMinStakeAmount(uint256 _minStakeAmount) external { + if (msg.sender != admin) revert Unauthorized(); + if (_minStakeAmount == 0) revert InvalidValue(); + minStakeAmount = _minStakeAmount; + emit MinStakeAmountUpdated(minStakeAmount); + } + + /// @notice Update the max churn rate + /// @dev The max churn rate cannot be set to zero + /// @param _maxChurnRate The new max churn rate + function updateMaxChurnRate(uint64 _maxChurnRate) external { + if (msg.sender != admin) revert Unauthorized(); + if (_maxChurnRate == 0) revert InvalidValue(); + maxChurnRate = _maxChurnRate; + emit MaxChurnRateUpdated(maxChurnRate); + } + + /// @notice Update the light client address + /// @dev The light client address cannot be set to the zero address + /// @param _lightClientAddress The new light client address + function updateLightClientAddress(address _lightClientAddress) external { + if (msg.sender != admin) revert Unauthorized(); + if (_lightClientAddress == address(0)) revert InvalidAddress(); + lightClient = LightClient(_lightClientAddress); + emit LightClientAddressUpdated(_lightClientAddress); } } diff --git a/contracts/src/interfaces/AbstractStakeTable.sol b/contracts/src/interfaces/AbstractStakeTable.sol index a73f285a2a..85cdd1430c 100644 --- a/contracts/src/interfaces/AbstractStakeTable.sol +++ b/contracts/src/interfaces/AbstractStakeTable.sol @@ -47,6 +47,22 @@ abstract contract AbstractStakeTable { address account, BN254.G2Point newBlsVK, EdOnBN254.EdOnBN254Point newSchnorrVK ); + /// @notice Signals the admin has been updated + /// @param admin the new admin + event AdminUpdated(address admin); + + /// @notice Signals the min stake amount has been updated + /// @param minStakeAmount the new min stake amount + event MinStakeAmountUpdated(uint256 minStakeAmount); + + /// @notice Signals the max churn rate has been updated + /// @param maxChurnRate the new max churn rate + event MaxChurnRateUpdated(uint256 maxChurnRate); + + /// @notice Signals the light client address has been updated + /// @param lightClientAddress the new light client address + event LightClientAddressUpdated(address lightClientAddress); + /// @dev (sadly, Solidity doesn't support type alias on non-primitive types) // We avoid declaring another struct even if the type info helps with readability, // extra layer of struct introduces overhead and more gas cost. diff --git a/contracts/test/StakeTable.t.sol b/contracts/test/StakeTable.t.sol index 414b86c22e..a84a442e2e 100644 --- a/contracts/test/StakeTable.t.sol +++ b/contracts/test/StakeTable.t.sol @@ -29,6 +29,7 @@ contract StakeTable_register_Test is Test { ExampleToken public token; LightClientMock public lcMock; uint256 public constant INITIAL_BALANCE = 10 ether; + uint256 public constant MIN_STAKE_AMOUNT = 10 ether; address public exampleTokenCreator; function genClientWallet(address sender, string memory seed) @@ -77,7 +78,7 @@ contract StakeTable_register_Test is Test { lcMock = new LightClientMock(genesis, genesisStakeTableState, 864000); address lightClientAddress = address(lcMock); - stakeTable = new S(address(token), lightClientAddress, 10); + stakeTable = new S(address(token), lightClientAddress, 10, MIN_STAKE_AMOUNT); } function testFuzz_RevertWhen_InvalidBLSSig(uint256 scalar) external { @@ -745,4 +746,80 @@ contract StakeTable_register_Test is Test { stakeTable.withdrawFunds(); vm.stopPrank(); } + + // test set admin succeeds + function test_setAdmin_succeeds() public { + vm.expectEmit(false, false, false, true, address(stakeTable)); + emit AbstractStakeTable.AdminUpdated(makeAddr("admin")); + stakeTable.updateAdmin(makeAddr("admin")); + assertEq(stakeTable.admin(), makeAddr("admin")); + } + + // test set admin fails if not admin or invalid admin address + function test_revertWhen_setAdmin_NotAdminOrInvalidAdminAddress() public { + vm.startPrank(makeAddr("randomUser")); + vm.expectRevert(S.Unauthorized.selector); + stakeTable.updateAdmin(makeAddr("admin")); + vm.stopPrank(); + + vm.expectRevert(S.InvalidAddress.selector); + stakeTable.updateAdmin(address(0)); + } + + // test update min stake amount succeeds + function test_updateMinStakeAmount_succeeds() public { + vm.expectEmit(false, false, false, true, address(stakeTable)); + emit AbstractStakeTable.MinStakeAmountUpdated(10 ether); + stakeTable.updateMinStakeAmount(10 ether); + assertEq(stakeTable.minStakeAmount(), 10 ether); + } + + // test update min stake amount fails if not admin or invalid stake amount + function test_revertWhen_updateMinStakeAmount_NotAdminOrInvalidStakeAmount() public { + vm.startPrank(makeAddr("randomUser")); + vm.expectRevert(S.Unauthorized.selector); + stakeTable.updateMinStakeAmount(10 ether); + vm.stopPrank(); + + vm.expectRevert(S.InvalidValue.selector); + stakeTable.updateMinStakeAmount(0); + } + + // test update max churn rate succeeds + function test_updateMaxChurnRate_succeeds() public { + vm.expectEmit(false, false, false, true, address(stakeTable)); + emit AbstractStakeTable.MaxChurnRateUpdated(10); + stakeTable.updateMaxChurnRate(10); + assertEq(stakeTable.maxChurnRate(), 10); + } + + // test update max churn rate fails if not admin or invalid churn amount + function test_revertWhen_updateMaxChurnRate_NotAdminOrInvalidChurnAmount() public { + vm.startPrank(makeAddr("randomUser")); + vm.expectRevert(S.Unauthorized.selector); + stakeTable.updateMaxChurnRate(10); + vm.stopPrank(); + + vm.expectRevert(S.InvalidValue.selector); + stakeTable.updateMaxChurnRate(0); + } + + // test update light client address succeeds + function test_updateLightClientAddress_succeeds() public { + vm.expectEmit(false, false, false, true, address(stakeTable)); + emit AbstractStakeTable.LightClientAddressUpdated(makeAddr("lightClient")); + stakeTable.updateLightClientAddress(makeAddr("lightClient")); + assertEq(address(stakeTable.lightClient()), makeAddr("lightClient")); + } + + // test update light client address fails if not admin or bad address + function test_revertWhen_updateLightClientAddress_NotAdminOrBadAddress() public { + vm.startPrank(makeAddr("randomUser")); + vm.expectRevert(S.Unauthorized.selector); + stakeTable.updateLightClientAddress(makeAddr("lightClient")); + vm.stopPrank(); + + vm.expectRevert(S.InvalidAddress.selector); + stakeTable.updateLightClientAddress(address(0)); + } } From dbcfeb3144509b493b104fd69fedb823d964cf16 Mon Sep 17 00:00:00 2001 From: Alysia Huggins Date: Wed, 5 Feb 2025 16:56:14 -0500 Subject: [PATCH 2/5] use Ownable for admin management --- contracts/src/StakeTable.sol | 35 +++++++----------------- contracts/test/StakeTable.t.sol | 48 +++++++++++++++++++++++++-------- 2 files changed, 46 insertions(+), 37 deletions(-) diff --git a/contracts/src/StakeTable.sol b/contracts/src/StakeTable.sol index 5e660c5196..fd3e8db1eb 100644 --- a/contracts/src/StakeTable.sol +++ b/contracts/src/StakeTable.sol @@ -6,11 +6,12 @@ import { BLSSig } from "./libraries/BLSSig.sol"; import { AbstractStakeTable } from "./interfaces/AbstractStakeTable.sol"; import { LightClient } from "../src/LightClient.sol"; import { EdOnBN254 } from "./libraries/EdOnBn254.sol"; +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; using EdOnBN254 for EdOnBN254.EdOnBN254Point; /// @title Implementation of the Stake Table interface -contract StakeTable is AbstractStakeTable { +contract StakeTable is AbstractStakeTable, Ownable { /// Error to notify restaking is not implemented yet. error RestakingNotImplemented(); @@ -64,7 +65,7 @@ contract StakeTable is AbstractStakeTable { // Error raised when zero point keys are provided error NoKeyChange(); - /// Error raised when the caller is not the admin + /// Error raised when the caller is not the owner error Unauthorized(); /// Error raised when the light client address is invalid @@ -103,15 +104,14 @@ contract StakeTable is AbstractStakeTable { uint256 public minStakeAmount; - address public admin; - /// TODO change constructor to initialize function when we make the contract upgradeable constructor( address _tokenAddress, address _lightClientAddress, uint64 churnRate, - uint256 _minStakeAmount - ) { + uint256 _minStakeAmount, + address initialOwner + ) Ownable(initialOwner) { tokenAddress = _tokenAddress; lightClient = LightClient(_lightClientAddress); @@ -126,8 +126,6 @@ contract StakeTable is AbstractStakeTable { _numPendingExits = 0; minStakeAmount = _minStakeAmount; - - admin = msg.sender; } /// @dev Computes a hash value of some G2 point. @@ -415,8 +413,6 @@ contract StakeTable is AbstractStakeTable { /// @notice Request to exit from the stake table, not immediately withdrawable! /// /// @dev TODO modify this according to the current spec - /// @dev TODO add a function to check if the node is eligible to exit - /// @dev TODO discuss if we want an admin administered emergency exit function requestExit() external override { Node memory node = nodes[msg.sender]; @@ -549,21 +545,10 @@ contract StakeTable is AbstractStakeTable { emit UpdatedConsensusKeys(msg.sender, node.blsVK, node.schnorrVK); } - /// @notice Update the admin - /// @dev The admin cannot be set to the zero address - /// @param _admin The new admin - function updateAdmin(address _admin) external { - if (msg.sender != admin) revert Unauthorized(); - if (_admin == address(0)) revert InvalidAddress(); - admin = _admin; - emit AdminUpdated(admin); - } - /// @notice Update the min stake amount /// @dev The min stake amount cannot be set to zero /// @param _minStakeAmount The new min stake amount - function updateMinStakeAmount(uint256 _minStakeAmount) external { - if (msg.sender != admin) revert Unauthorized(); + function updateMinStakeAmount(uint256 _minStakeAmount) external onlyOwner { if (_minStakeAmount == 0) revert InvalidValue(); minStakeAmount = _minStakeAmount; emit MinStakeAmountUpdated(minStakeAmount); @@ -572,8 +557,7 @@ contract StakeTable is AbstractStakeTable { /// @notice Update the max churn rate /// @dev The max churn rate cannot be set to zero /// @param _maxChurnRate The new max churn rate - function updateMaxChurnRate(uint64 _maxChurnRate) external { - if (msg.sender != admin) revert Unauthorized(); + function updateMaxChurnRate(uint64 _maxChurnRate) external onlyOwner { if (_maxChurnRate == 0) revert InvalidValue(); maxChurnRate = _maxChurnRate; emit MaxChurnRateUpdated(maxChurnRate); @@ -582,8 +566,7 @@ contract StakeTable is AbstractStakeTable { /// @notice Update the light client address /// @dev The light client address cannot be set to the zero address /// @param _lightClientAddress The new light client address - function updateLightClientAddress(address _lightClientAddress) external { - if (msg.sender != admin) revert Unauthorized(); + function updateLightClientAddress(address _lightClientAddress) external onlyOwner { if (_lightClientAddress == address(0)) revert InvalidAddress(); lightClient = LightClient(_lightClientAddress); emit LightClientAddressUpdated(_lightClientAddress); diff --git a/contracts/test/StakeTable.t.sol b/contracts/test/StakeTable.t.sol index a84a442e2e..9d5092b19d 100644 --- a/contracts/test/StakeTable.t.sol +++ b/contracts/test/StakeTable.t.sol @@ -17,6 +17,7 @@ import { EdOnBN254 } from "../src/libraries/EdOnBn254.sol"; import { AbstractStakeTable } from "../src/interfaces/AbstractStakeTable.sol"; import { LightClient } from "../src/LightClient.sol"; import { LightClientMock } from "../test/mocks/LightClientMock.sol"; +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; // Token contract import { ExampleToken } from "../src/ExampleToken.sol"; @@ -78,7 +79,8 @@ contract StakeTable_register_Test is Test { lcMock = new LightClientMock(genesis, genesisStakeTableState, 864000); address lightClientAddress = address(lcMock); - stakeTable = new S(address(token), lightClientAddress, 10, MIN_STAKE_AMOUNT); + stakeTable = + new S(address(token), lightClientAddress, 10, MIN_STAKE_AMOUNT, exampleTokenCreator); } function testFuzz_RevertWhen_InvalidBLSSig(uint256 scalar) external { @@ -749,25 +751,32 @@ contract StakeTable_register_Test is Test { // test set admin succeeds function test_setAdmin_succeeds() public { + vm.prank(exampleTokenCreator); vm.expectEmit(false, false, false, true, address(stakeTable)); - emit AbstractStakeTable.AdminUpdated(makeAddr("admin")); - stakeTable.updateAdmin(makeAddr("admin")); - assertEq(stakeTable.admin(), makeAddr("admin")); + emit Ownable.OwnershipTransferred(exampleTokenCreator, makeAddr("admin")); + stakeTable.transferOwnership(makeAddr("admin")); + assertEq(stakeTable.owner(), makeAddr("admin")); } // test set admin fails if not admin or invalid admin address function test_revertWhen_setAdmin_NotAdminOrInvalidAdminAddress() public { vm.startPrank(makeAddr("randomUser")); - vm.expectRevert(S.Unauthorized.selector); - stakeTable.updateAdmin(makeAddr("admin")); + vm.expectRevert( + abi.encodeWithSelector( + Ownable.OwnableUnauthorizedAccount.selector, makeAddr("randomUser") + ) + ); + stakeTable.transferOwnership(makeAddr("admin")); vm.stopPrank(); - vm.expectRevert(S.InvalidAddress.selector); - stakeTable.updateAdmin(address(0)); + vm.prank(exampleTokenCreator); + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableInvalidOwner.selector, address(0))); + stakeTable.transferOwnership(address(0)); } // test update min stake amount succeeds function test_updateMinStakeAmount_succeeds() public { + vm.prank(exampleTokenCreator); vm.expectEmit(false, false, false, true, address(stakeTable)); emit AbstractStakeTable.MinStakeAmountUpdated(10 ether); stakeTable.updateMinStakeAmount(10 ether); @@ -777,16 +786,22 @@ contract StakeTable_register_Test is Test { // test update min stake amount fails if not admin or invalid stake amount function test_revertWhen_updateMinStakeAmount_NotAdminOrInvalidStakeAmount() public { vm.startPrank(makeAddr("randomUser")); - vm.expectRevert(S.Unauthorized.selector); + vm.expectRevert( + abi.encodeWithSelector( + Ownable.OwnableUnauthorizedAccount.selector, makeAddr("randomUser") + ) + ); stakeTable.updateMinStakeAmount(10 ether); vm.stopPrank(); + vm.prank(exampleTokenCreator); vm.expectRevert(S.InvalidValue.selector); stakeTable.updateMinStakeAmount(0); } // test update max churn rate succeeds function test_updateMaxChurnRate_succeeds() public { + vm.prank(exampleTokenCreator); vm.expectEmit(false, false, false, true, address(stakeTable)); emit AbstractStakeTable.MaxChurnRateUpdated(10); stakeTable.updateMaxChurnRate(10); @@ -796,16 +811,22 @@ contract StakeTable_register_Test is Test { // test update max churn rate fails if not admin or invalid churn amount function test_revertWhen_updateMaxChurnRate_NotAdminOrInvalidChurnAmount() public { vm.startPrank(makeAddr("randomUser")); - vm.expectRevert(S.Unauthorized.selector); + vm.expectRevert( + abi.encodeWithSelector( + Ownable.OwnableUnauthorizedAccount.selector, makeAddr("randomUser") + ) + ); stakeTable.updateMaxChurnRate(10); vm.stopPrank(); + vm.prank(exampleTokenCreator); vm.expectRevert(S.InvalidValue.selector); stakeTable.updateMaxChurnRate(0); } // test update light client address succeeds function test_updateLightClientAddress_succeeds() public { + vm.prank(exampleTokenCreator); vm.expectEmit(false, false, false, true, address(stakeTable)); emit AbstractStakeTable.LightClientAddressUpdated(makeAddr("lightClient")); stakeTable.updateLightClientAddress(makeAddr("lightClient")); @@ -815,10 +836,15 @@ contract StakeTable_register_Test is Test { // test update light client address fails if not admin or bad address function test_revertWhen_updateLightClientAddress_NotAdminOrBadAddress() public { vm.startPrank(makeAddr("randomUser")); - vm.expectRevert(S.Unauthorized.selector); + vm.expectRevert( + abi.encodeWithSelector( + Ownable.OwnableUnauthorizedAccount.selector, makeAddr("randomUser") + ) + ); stakeTable.updateLightClientAddress(makeAddr("lightClient")); vm.stopPrank(); + vm.prank(exampleTokenCreator); vm.expectRevert(S.InvalidAddress.selector); stakeTable.updateLightClientAddress(address(0)); } From 9edcc699c4b59ee9d6d3dfa793d82cdc1b64b524 Mon Sep 17 00:00:00 2001 From: Alysia Huggins Date: Wed, 5 Feb 2025 16:59:39 -0500 Subject: [PATCH 3/5] remove AdminUpdated event --- contracts/src/interfaces/AbstractStakeTable.sol | 4 ---- 1 file changed, 4 deletions(-) diff --git a/contracts/src/interfaces/AbstractStakeTable.sol b/contracts/src/interfaces/AbstractStakeTable.sol index 85cdd1430c..a5563202d9 100644 --- a/contracts/src/interfaces/AbstractStakeTable.sol +++ b/contracts/src/interfaces/AbstractStakeTable.sol @@ -47,10 +47,6 @@ abstract contract AbstractStakeTable { address account, BN254.G2Point newBlsVK, EdOnBN254.EdOnBN254Point newSchnorrVK ); - /// @notice Signals the admin has been updated - /// @param admin the new admin - event AdminUpdated(address admin); - /// @notice Signals the min stake amount has been updated /// @param minStakeAmount the new min stake amount event MinStakeAmountUpdated(uint256 minStakeAmount); From 2feda042ff490bac38de6566e0880bbf16993705 Mon Sep 17 00:00:00 2001 From: Alysia Huggins Date: Thu, 6 Feb 2025 11:16:22 -0500 Subject: [PATCH 4/5] register with variable stake amount --- contracts/src/StakeTable.sol | 20 ++++++++------------ contracts/test/StakeTable.t.sol | 2 +- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/contracts/src/StakeTable.sol b/contracts/src/StakeTable.sol index fd3e8db1eb..e48e450d09 100644 --- a/contracts/src/StakeTable.sol +++ b/contracts/src/StakeTable.sol @@ -290,10 +290,8 @@ contract StakeTable is AbstractStakeTable, Ownable { BN254.G1Point memory blsSig, uint64 validUntilEpoch ) external override { - uint256 fixedStakeAmount = minStakeAmount; - // Verify that the sender amount is the minStakeAmount - if (amount < fixedStakeAmount) { + if (amount < minStakeAmount) { revert InsufficientStakeAmount(amount); } @@ -306,13 +304,13 @@ contract StakeTable is AbstractStakeTable, Ownable { // Verify that this contract has permissions to access the validator's stake token. uint256 allowance = ERC20(tokenAddress).allowance(msg.sender, address(this)); - if (allowance < fixedStakeAmount) { - revert InsufficientAllowance(allowance, fixedStakeAmount); + if (allowance < amount) { + revert InsufficientAllowance(allowance, amount); } // Verify that the validator has the balance for this stake token. uint256 balance = ERC20(tokenAddress).balanceOf(msg.sender); - if (balance < fixedStakeAmount) { + if (balance < amount) { revert InsufficientBalance(balance); } @@ -351,23 +349,21 @@ contract StakeTable is AbstractStakeTable, Ownable { appendRegistrationQueue(registerEpoch, queueSize); // Transfer the stake amount of ERC20 tokens from the sender to this contract. - SafeTransferLib.safeTransferFrom( - ERC20(tokenAddress), msg.sender, address(this), fixedStakeAmount - ); + SafeTransferLib.safeTransferFrom(ERC20(tokenAddress), msg.sender, address(this), amount); // Update the total staked amount - totalStake += fixedStakeAmount; + totalStake += amount; // Create an entry for the node. node.account = msg.sender; - node.balance = fixedStakeAmount; + node.balance = amount; node.blsVK = blsVK; node.schnorrVK = schnorrVK; node.registerEpoch = registerEpoch; nodes[msg.sender] = node; - emit Registered(msg.sender, registerEpoch, fixedStakeAmount); + emit Registered(msg.sender, registerEpoch, amount); } /// @notice Deposit more stakes to registered keys diff --git a/contracts/test/StakeTable.t.sol b/contracts/test/StakeTable.t.sol index 9d5092b19d..3cf7a6ef9a 100644 --- a/contracts/test/StakeTable.t.sol +++ b/contracts/test/StakeTable.t.sol @@ -207,7 +207,7 @@ contract StakeTable_register_Test is Test { } function test_RevertWhen_WrongStakeAmount() external { - uint64 depositAmount = 5 ether; + uint64 depositAmount = uint64(stakeTable.minStakeAmount()) - 1; uint64 validUntilEpoch = 10; string memory seed = "123"; From 5dcb69738312f818275b7b76487787f5c04feb61 Mon Sep 17 00:00:00 2001 From: Alysia Huggins Date: Thu, 6 Feb 2025 21:55:31 -0500 Subject: [PATCH 5/5] rename test --- contracts/test/StakeTable.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/test/StakeTable.t.sol b/contracts/test/StakeTable.t.sol index 3cf7a6ef9a..434a31f683 100644 --- a/contracts/test/StakeTable.t.sol +++ b/contracts/test/StakeTable.t.sol @@ -206,7 +206,7 @@ contract StakeTable_register_Test is Test { vm.stopPrank(); } - function test_RevertWhen_WrongStakeAmount() external { + function test_RevertWhen_InsufficientStakeAmount() external { uint64 depositAmount = uint64(stakeTable.minStakeAmount()) - 1; uint64 validUntilEpoch = 10; string memory seed = "123";