From bbfd108d3a612af2096ebc0a462ad509f08167c5 Mon Sep 17 00:00:00 2001 From: Iulian Rotaru Date: Tue, 29 Mar 2022 12:31:08 +0200 Subject: [PATCH] feat: resolve review points --- .prettierignore | 6 + src/StakingContract.sol | 225 ++++++++++------- src/test/StakingContract.t.sol | 443 +++++++++++++++------------------ 3 files changed, 346 insertions(+), 328 deletions(-) create mode 100644 .prettierignore diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..6fb3a12 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,6 @@ +node_modules +artifacts +cache +coverage* +gasReporterOutput.json +deploy/*.ts diff --git a/src/StakingContract.sol b/src/StakingContract.sol index 2c2f911..2ecb4b7 100644 --- a/src/StakingContract.sol +++ b/src/StakingContract.sol @@ -11,35 +11,46 @@ import "./test/console.sol"; contract StakingContract { using StateLib for bytes32; - // review(nmvalera): we can hard code all *_SLOT values - bytes32 internal constant FEE_SLOT = keccak256("StakingContract.fee"); - bytes32 internal constant ADMIN_SLOT = keccak256("StakingContract.admin"); + bytes32 internal constant VERSION_SLOT = + /* keccak256("StakingContract.version") */ + hex"d5c553085b8382c47128ae7612257fd5dc3b4fc4d3a108925604d3c8700c025b"; + bytes32 internal constant OPERATOR_SLOT = + /* keccak256("StakingContract.operator") */ + hex"dfe7334ae89a4aa54c085540947bfa7e13e6b6933be4c49f359d18e88c0dbde5"; + bytes32 internal constant SIGNATURES_SLOT = + /* keccak256("StakingContract.signatures") */ + hex"2805e4a7c8c139ac2ebe63141d90c488245fd479906b2c60bd42603b8a2ca08b"; + bytes32 internal constant PUBLIC_KEYS_SLOT = + /* keccak256("StakingContract.publicKeys") */ + hex"cc0b8384259c4a4e6418cdc72955757e9214822019f44d8b5283077c1b46d43c"; + bytes32 internal constant WITHDRAWERS_SLOT = + /* keccak256("StakingContract.withdrawers") */ + hex"86647fdbbdb534026d3e0f93a551cecf651c2b40fcdfef4b9fd9ed826133e265"; + bytes32 internal constant VALIDATORS_COUNT_SLOT = + /* keccak256("StakingContract.validatorsCount") */ + hex"e9622dd0bba60226e1dbc661ca8aae56cc90dc7e9b3f33ece002f6764b3801b8"; + bytes32 internal constant DEPOSIT_CONTRACT_SLOT = + /* keccak256("StakingContract.depositContract") */ + hex"bc8b9852d17d50256bb221fdf6ee12d78dd493d807e907f7d223c40d65abd6b9"; + bytes32 internal constant WITHDRAWAL_CREDENTIALS_SLOT = + /* keccak256("StakingContract.withdrawalCredentials") */ + hex"2783da738595cd6ebaec6fd0f06d62f2266a9e475e2d1feb1d26aa2d1e051255"; - // review(nmvalera): can we add an entry for the node operator like OPERATOR_SLOT - bytes32 internal constant VERSION_SLOT = keccak256("StakingContract.version"); - bytes32 internal constant SIGNATURES_SLOT = keccak256("StakingContract.signatures"); - bytes32 internal constant PUBLIC_KEYS_SLOT = keccak256("StakingContract.publicKeys"); - - // review(nmvalera): rename VALIDATOR_COUNT_SLOT -> VALIDATORS_COUNT_SLOT - bytes32 internal constant VALIDATOR_COUNT_SLOT = keccak256("StakingContract.validatorCount"); - bytes32 internal constant DEPOSIT_CONTRACT_SLOT = keccak256("StakingContract.depositContract"); - - // review(nmvalera): rename PUBLIC_KEY_OWNERSHIP_SLOT -> WITHDRAWERS_SLOT - bytes32 internal constant PUBLIC_KEY_OWNERSHIP_SLOT = keccak256("StakingContract.publicKeyOwnership"); - bytes32 internal constant WITHDRAWAL_CREDENTIALS_SLOT = keccak256("StakingContract.withdrawalCredentials"); - - // review(nmvalera): can we add an entry for the operator - - uint256 public constant DEPOSIT_SIZE = 32 ether; - uint256 public constant PUBLIC_KEY_LENGTH = 48; uint256 public constant SIGNATURE_LENGTH = 96; + uint256 public constant PUBLIC_KEY_LENGTH = 48; + uint256 public constant DEPOSIT_SIZE = 32 ether; - error Unauthorized(); - error AlreadyInitialized(); error InvalidCall(); - error InvalidArgument(); - error InvalidValue(); + error Unauthorized(); error NotEnoughKeys(); + error DepositFailure(); + error InvalidArgument(); + error UnsortedIndexes(); + error InvalidPublicKeys(); + error InvalidSignatures(); + error AlreadyInitialized(); + error InvalidMessageValue(); + error FundedValidatorDeletionAttempt(); event Deposit(address indexed caller, address indexed withdrawer, bytes publicKey, bytes32 publicKeyRoot); @@ -53,8 +64,8 @@ contract StakingContract { _; } - modifier onlyAdmin() { - if (msg.sender != ADMIN_SLOT.getAddress()) { + modifier onlyOperator() { + if (msg.sender != OPERATOR_SLOT.getAddress()) { revert Unauthorized(); } @@ -62,38 +73,30 @@ contract StakingContract { } function initialize_1( - address _admin, - uint256 _fee, + address _operator, address _depositContract, bytes32 _withdrawalCredentials ) external init(1) { - ADMIN_SLOT.setAddress(_admin); - FEE_SLOT.setUint256(_fee); + OPERATOR_SLOT.setAddress(_operator); DEPOSIT_CONTRACT_SLOT.setAddress(_depositContract); WITHDRAWAL_CREDENTIALS_SLOT.setBytes32(_withdrawalCredentials); } - // review(nmvalera): if I understand correctly this one should be named fundedValidatorsCount() - function getValidatorCount() external view returns (uint256) { - return VALIDATOR_COUNT_SLOT.getUint256(); + function fundedValidatorsCount() external view returns (uint256) { + return VALIDATORS_COUNT_SLOT.getUint256(); } - // question(nmvalera): rename getKeyCount -> totalValidatorCount - function getKeyCount() external view returns (uint256) { + function totalValidatorCount() external view returns (uint256) { return PUBLIC_KEYS_SLOT.getStorageBytesArray().value.length; } function getWithdrawer(bytes memory _publicKey) external view returns (address) { bytes32 pubkeyRoot = sha256(BytesLib.pad64(_publicKey)); - StateLib.Bytes32ToAddressMappingSlot storage publicKeyOwnership = PUBLIC_KEY_OWNERSHIP_SLOT + StateLib.Bytes32ToAddressMappingSlot storage publicKeyOwnership = WITHDRAWERS_SLOT .getStorageBytes32ToAddressMapping(); return publicKeyOwnership.value[pubkeyRoot]; } - function getFee() external view returns (uint256) { - return FEE_SLOT.getUint256(); - } - function deposit(address _withdrawer) external payable { _deposit(_withdrawer); } @@ -106,61 +109,110 @@ contract StakingContract { revert InvalidCall(); } - // review(nmvalera): rename to registerValidators - // review(nmvalera): modifier should be onlyOperator (modifier to be created) - // review(nmvalera): why not doing the same as River function addValidators(uint256 _keyCount,bytes calldata _publicKeys, bytes calldata _signatures)? It will be easier for skillz to operate all contracts the same way - function registerValidatorKeys(bytes[] memory publicKeys, bytes[] memory signatures) external onlyAdmin { - if (publicKeys.length != signatures.length || publicKeys.length == 0) { + function registerValidators( + uint256 keyCount, + bytes calldata publicKeys, + bytes calldata signatures + ) external onlyOperator { + if (keyCount == 0) { revert InvalidArgument(); } + if (publicKeys.length % PUBLIC_KEY_LENGTH != 0 || publicKeys.length / PUBLIC_KEY_LENGTH != keyCount) { + revert InvalidPublicKeys(); + } + + if (signatures.length % SIGNATURE_LENGTH != 0 || signatures.length / SIGNATURE_LENGTH != keyCount) { + revert InvalidSignatures(); + } StateLib.BytesArraySlot storage publicKeysStore = PUBLIC_KEYS_SLOT.getStorageBytesArray(); StateLib.BytesArraySlot storage signaturesStore = SIGNATURES_SLOT.getStorageBytesArray(); - for (uint256 i; i < publicKeys.length; ) { - if (publicKeys[i].length != 48 || signatures[i].length != 96) { - // review(nmvalera): is it possible to be more explicit in the message, like "invalid pubkey at position {i} has length {publicKeys[i].length} expects 48" - revert InvalidArgument(); + for (uint256 i; i < keyCount; ) { + bytes memory publicKey = BytesLib.slice(publicKeys, i * PUBLIC_KEY_LENGTH, PUBLIC_KEY_LENGTH); + bytes memory signature = BytesLib.slice(signatures, i * SIGNATURE_LENGTH, SIGNATURE_LENGTH); + + publicKeysStore.value.push(publicKey); + signaturesStore.value.push(signature); + + unchecked { + ++i; } - publicKeysStore.value.push(publicKeys[i]); - signaturesStore.value.push(signatures[i]); - // question(nmvalera): what does unchecked mean? + } + } + + function removeValidators(uint256[] calldata _indexes) external onlyOperator { + if (_indexes.length == 0) { + revert InvalidArgument(); + } + + uint256 validatorsCount = VALIDATORS_COUNT_SLOT.getUint256(); + StateLib.BytesArraySlot storage publicKeysStore = PUBLIC_KEYS_SLOT.getStorageBytesArray(); + StateLib.BytesArraySlot storage signaturesStore = SIGNATURES_SLOT.getStorageBytesArray(); + + for (uint256 i; i < _indexes.length; ) { + if (i > 0 && _indexes[i] >= _indexes[i - 1]) { + revert UnsortedIndexes(); + } + + if (_indexes[i] < validatorsCount) { + revert FundedValidatorDeletionAttempt(); + } + + if (_indexes[i] == publicKeysStore.value.length - 1) { + publicKeysStore.value.pop(); + signaturesStore.value.pop(); + } else { + publicKeysStore.value[_indexes[i]] = publicKeysStore.value[publicKeysStore.value.length - 1]; + publicKeysStore.value.pop(); + signaturesStore.value[_indexes[i]] = signaturesStore.value[signaturesStore.value.length - 1]; + signaturesStore.value.pop(); + } + unchecked { ++i; } } } - // review(nmvalera): add a method getValidator(uint256 _idx) that returns a validator (pubkey, signature, withdrawer, and funded) + function getValidator(uint256 _idx) + external + view + returns ( + bytes memory publicKey, + bytes memory signature, + address withdrawer, + bool funded + ) + { + StateLib.BytesArraySlot storage publicKeysStore = PUBLIC_KEYS_SLOT.getStorageBytesArray(); + StateLib.BytesArraySlot storage signaturesStore = SIGNATURES_SLOT.getStorageBytesArray(); + StateLib.Bytes32ToAddressMappingSlot storage withdrawers = WITHDRAWERS_SLOT.getStorageBytes32ToAddressMapping(); + uint256 validatorCount = VALIDATORS_COUNT_SLOT.getUint256(); - // review(nmvalera): add a method removeValidators(uint256[] calldata _indexes) + publicKey = publicKeysStore.value[_idx]; + signature = signaturesStore.value[_idx]; + withdrawer = withdrawers.value[sha256(BytesLib.pad64(publicKey))]; + funded = _idx < validatorCount; + } function setWithdrawer(bytes memory _publicKey, address _newWithdrawer) external { bytes32 pubkeyRoot = sha256(BytesLib.pad64(_publicKey)); - StateLib.Bytes32ToAddressMappingSlot storage publicKeyOwnership = PUBLIC_KEY_OWNERSHIP_SLOT + StateLib.Bytes32ToAddressMappingSlot storage publicKeyOwnership = WITHDRAWERS_SLOT .getStorageBytes32ToAddressMapping(); if (msg.sender != publicKeyOwnership.value[pubkeyRoot]) { - // review(nmvalera): is it possible to be more explicit in the message, like "{msg.sender} is not the withdrawer for {_publicKey}" revert Unauthorized(); } publicKeyOwnership.value[pubkeyRoot] = _newWithdrawer; } - // review(nmvalera): following up on discussion with ledger we should not need the fee upfront - function setFee(uint256 _newFee) external onlyAdmin { - FEE_SLOT.setUint256(_newFee); - } - - // review(nmvalera): rename _useKeys -> _depositValidator - function _useKeys( - // review(nmvalera): rename _publicKey -> _pubkey (let's try to be consistent every where using pubkey and not publicKey) + function _depositValidator( bytes memory _publicKey, bytes memory _signature, - bytes32 _withdrawalCredentials, - address _withdrawer + bytes32 _withdrawalCredentials ) internal { bytes32 pubkeyRoot = sha256(BytesLib.pad64(_publicKey)); bytes32 signatureRoot = sha256( @@ -189,29 +241,18 @@ contract StakingContract { depositDataRoot ); - require(address(this).balance == targetBalance, "EXPECTING_DEPOSIT_TO_HAPPEN"); - - // review(nmvalera): seems that setting withdrawer and emitting Deposit event should be part of _deposit() function. 2 reasons: - // 1. we scope the responsibility of _useKeys() to only depositing a key to the official deposit contract - // 2. we avoid to load storage publicKeyOwnership at every step of the loop - StateLib.Bytes32ToAddressMappingSlot storage publicKeyOwnership = PUBLIC_KEY_OWNERSHIP_SLOT - .getStorageBytes32ToAddressMapping(); - - publicKeyOwnership.value[pubkeyRoot] = _withdrawer; - - emit Deposit(msg.sender, _withdrawer, _publicKey, pubkeyRoot); + if (address(this).balance != targetBalance) { + revert DepositFailure(); + } } function _deposit(address _withdrawer) internal { - uint256 fee = FEE_SLOT.getUint256(); - - if (msg.value == 0 || msg.value % (DEPOSIT_SIZE + fee) != 0) { - // review(nmvalera): can we make the message more explicit like "expects value to be a multiple of {DEPOSIT_SIZE + fee} but got {msg.value} - revert InvalidValue(); + if (msg.value == 0 || msg.value % DEPOSIT_SIZE != 0) { + revert InvalidMessageValue(); } - uint256 depositCount = msg.value / (DEPOSIT_SIZE + fee); - uint256 validatorCount = VALIDATOR_COUNT_SLOT.getUint256(); + uint256 depositCount = msg.value / DEPOSIT_SIZE; + uint256 validatorCount = VALIDATORS_COUNT_SLOT.getUint256(); StateLib.BytesArraySlot storage publicKeysStore = PUBLIC_KEYS_SLOT.getStorageBytesArray(); StateLib.BytesArraySlot storage signaturesStore = SIGNATURES_SLOT.getStorageBytesArray(); bytes32 withdrawalCredentials = WITHDRAWAL_CREDENTIALS_SLOT.getBytes32(); @@ -220,18 +261,20 @@ contract StakingContract { revert NotEnoughKeys(); } + StateLib.Bytes32ToAddressMappingSlot storage publicKeyOwnership = WITHDRAWERS_SLOT + .getStorageBytes32ToAddressMapping(); + for (uint256 i; i < depositCount; ) { - _useKeys( - publicKeysStore.value[validatorCount + i], - signaturesStore.value[validatorCount + i], - withdrawalCredentials, - _withdrawer - ); + bytes memory publicKey = publicKeysStore.value[validatorCount + i]; + bytes32 publicKeyRoot = sha256(BytesLib.pad64(publicKey)); + _depositValidator(publicKey, signaturesStore.value[validatorCount + i], withdrawalCredentials); + publicKeyOwnership.value[publicKeyRoot] = _withdrawer; + emit Deposit(msg.sender, _withdrawer, publicKey, publicKeyRoot); unchecked { ++i; } } - VALIDATOR_COUNT_SLOT.setUint256(validatorCount + depositCount); + VALIDATORS_COUNT_SLOT.setUint256(validatorCount + depositCount); } } diff --git a/src/test/StakingContract.t.sol b/src/test/StakingContract.t.sol index 179bba3..b874047 100644 --- a/src/test/StakingContract.t.sol +++ b/src/test/StakingContract.t.sol @@ -48,7 +48,7 @@ contract StakingContractTest is DSTestPlus { StakingContract internal stakingContract; DepositContractMock internal depositContract; - address internal admin = address(1); + address internal operator = address(1); address internal bob = address(2); address internal alice = address(3); @@ -57,248 +57,217 @@ contract StakingContractTest is DSTestPlus { function setUp() public { stakingContract = new StakingContract(); depositContract = new DepositContractMock(); - stakingContract.initialize_1(admin, 0.1 ether, address(depositContract), withdrawalCredentials); - - bytes[] memory publicKeys = new bytes[](10); - publicKeys[ - 0 - ] = hex"21d2e725aef3a8f9e09d8f4034948bb7f79505fc7c40e7a7ca15734bad4220a594bf0c6257cef7db88d9fc3fd4360759"; - publicKeys[ - 1 - ] = hex"b0ce3fa164aae897adca509ed44429e7b1f91b7c46ddbe199cee848e09b1ccbb9736b78b68aacff1011b7266fe11e060"; - publicKeys[ - 2 - ] = hex"14451b3fb9288549aff6dea9843b43e0c47a3b856f307732175230e254c0004e48b02414987088ac7003e148930017b4"; - publicKeys[ - 3 - ] = hex"9a1a8d4600f33d463c4afc07bbfc82703c9fcf81a5891f90a71c86a02faff443c6c3b2592bd44d5d3d7a93cb4aaaa105"; - publicKeys[ - 4 - ] = hex"612496d61e68140a5418b468f872bf2f3e79f9cb0d9c3e889663fca02939b31e8ee3092203ee1417128e965c6406a07f"; - publicKeys[ - 5 - ] = hex"68abf2ebe2689cf6c853ef126ffa8574c2a7d913e28de9147fa6b96706ea5bf9eacd1aba06edeaee155009fb912c0007"; - publicKeys[ - 6 - ] = hex"0774cc64136fcffde12ed731260bc5529df64da298f493561198e9d6acf42cf21e853ae7b2df85f27d2183149969d623"; - publicKeys[ - 7 - ] = hex"b9237254c2cfe1d0082742eb042ac096d686dbe03c79ee31cbd03bb4682f8797043eed9f6e622814831ac5dfe1176552"; - publicKeys[ - 8 - ] = hex"fb7f9b6ff38a149ae1d8414097a32fd96da6453c52fda13e3402a09e2fa6886daa4300f09c73e4bc2901b99c44744c5c"; - publicKeys[ - 9 - ] = hex"fdca2994adc49ddccb195bda2510e50a4ae10de26cf96dee5e577689f51650a610a33da0a826ae47247d8d1189cb3386"; - - bytes[] memory signatures = new bytes[](10); - signatures[ - 0 - ] = hex"ccb81f4485957f440bc17dbe760f374cbb112c6f12fa10e8709fac4522b30440d918c7bb867fa04f6b3cfbd977455f8f2fde586fdf3d7baa429e98e497ff871f3b8db1528b2b964fa24d26e377c74746496cc719c50dbf391fb3f74f5ca4b93a"; - signatures[ - 1 - ] = hex"02a9f0007cd7b7d2af2d1b07c8600ab86a5d27dc51a29c2e3007c7a69cb73bcaecc764641e02370955dba100428d259d6475ee3566872bd43b0e73e55b9669e50f2b1666e57b326a5dfad655c7921e0dfb421b1ec59c8fdb48eb77421fd06966"; - signatures[ - 2 - ] = hex"f393d619cbf13ff427df11dcb17026df25f35268de5b168e359c16f2a3d5fbc6376db44638d773c851c875f21222448433d285920e8bdc4f5cbff130d7387c0a9589324286aea398e5aacad3bbfe3992dfce62571f0e282ed9c29e3fa5b07aa5"; - signatures[ - 3 - ] = hex"c81749589b1170d3b85a84331e2f6b8e26eadebfd569b225759f40bbd12d6c3d253ed3f379b014b2ea44cce54d362072e2d020ff139a903b7d87fc3fddc2e6657c83e0b79851c22c6e0e477463463c97d6cc0e2e2de5e35b227bddb285521be3"; - signatures[ - 4 - ] = hex"766358abaf3159d89f68c9770e28278f177088cfc4089b817effaaecabdffa4e66427868b105cb9348ea2d84eeea059a5d1ff3277d6f9cf656fc973d07cabed70fb8f8eb2798a65d207a8e1f8a26910949db9fa62d62bc15ecc097a93a27a187"; - signatures[ - 5 - ] = hex"3405b8589a4ddf0ecf0303c6031484562b32eb7881975026524d6d4a9de6cd73fe2c324501586b9b6fa6bce950bbd21472278302f83dbfd6be036f2fc36d299d66578e844be3d6aa8314fab468f038fd6e130ada0a886fccfb2fd843f7dd07e8"; - signatures[ - 6 - ] = hex"968401bbe2af7345fce52ba4b310b30af2d54b15669d06c206682c1730ab6b17787e361f04401f78dc5cbd5fac955df4e83c24cdabfabdb3f4ea40961d04a5ca166c17694fca144025b47131a68ddb230d36fe6e831e82624c9a925d706bff86"; - signatures[ - 7 - ] = hex"982852b26ebf019a3f6ee36aedbbc6bec2d50531a233e09225493d3c5fd48379aec373baf622fb9feed6261e5296e5ae6601e7523c7f386801ed63a344b07106a0d03e5848209db5e114c0e67884916a43a1bfb77d9b8ea113c3ba8cad4b006a"; - signatures[ - 8 - ] = hex"afeadcc31e70e85c5efecaf807154d011c1413340d4b592d2f270fb48b2050e08493c1427ddfac8dcc27fe434d32a35dcbddbcb1c4e22ead6734a4ac910f6768bc9ff6b355c1151695e41121cdcc9d9d3b18cf4d66ca3c1db0527c471a0dcf25"; - signatures[ - 9 - ] = hex"6590602a7269dcb26175e7eb370bd9794ac8ab558bea69e6a92d8e818b675a80e2df0516b8307291d93cb85d959ac60d47b46455a7ab0a38687c747c6d2d9e8c20ccf74dc6cdf145ec06805d4ac24a39aec2f5cd6e26e63e3d043a31c42411e4"; - - vm.startPrank(admin); - stakingContract.registerValidatorKeys(publicKeys, signatures); + stakingContract.initialize_1(operator, address(depositContract), withdrawalCredentials); + + bytes + memory publicKeys = hex"21d2e725aef3a8f9e09d8f4034948bb7f79505fc7c40e7a7ca15734bad4220a594bf0c6257cef7db88d9fc3fd4360759b0ce3fa164aae897adca509ed44429e7b1f91b7c46ddbe199cee848e09b1ccbb9736b78b68aacff1011b7266fe11e06014451b3fb9288549aff6dea9843b43e0c47a3b856f307732175230e254c0004e48b02414987088ac7003e148930017b49a1a8d4600f33d463c4afc07bbfc82703c9fcf81a5891f90a71c86a02faff443c6c3b2592bd44d5d3d7a93cb4aaaa105612496d61e68140a5418b468f872bf2f3e79f9cb0d9c3e889663fca02939b31e8ee3092203ee1417128e965c6406a07f68abf2ebe2689cf6c853ef126ffa8574c2a7d913e28de9147fa6b96706ea5bf9eacd1aba06edeaee155009fb912c00070774cc64136fcffde12ed731260bc5529df64da298f493561198e9d6acf42cf21e853ae7b2df85f27d2183149969d623b9237254c2cfe1d0082742eb042ac096d686dbe03c79ee31cbd03bb4682f8797043eed9f6e622814831ac5dfe1176552fb7f9b6ff38a149ae1d8414097a32fd96da6453c52fda13e3402a09e2fa6886daa4300f09c73e4bc2901b99c44744c5cfdca2994adc49ddccb195bda2510e50a4ae10de26cf96dee5e577689f51650a610a33da0a826ae47247d8d1189cb3386"; + + bytes + memory signatures = hex"ccb81f4485957f440bc17dbe760f374cbb112c6f12fa10e8709fac4522b30440d918c7bb867fa04f6b3cfbd977455f8f2fde586fdf3d7baa429e98e497ff871f3b8db1528b2b964fa24d26e377c74746496cc719c50dbf391fb3f74f5ca4b93a02a9f0007cd7b7d2af2d1b07c8600ab86a5d27dc51a29c2e3007c7a69cb73bcaecc764641e02370955dba100428d259d6475ee3566872bd43b0e73e55b9669e50f2b1666e57b326a5dfad655c7921e0dfb421b1ec59c8fdb48eb77421fd06966f393d619cbf13ff427df11dcb17026df25f35268de5b168e359c16f2a3d5fbc6376db44638d773c851c875f21222448433d285920e8bdc4f5cbff130d7387c0a9589324286aea398e5aacad3bbfe3992dfce62571f0e282ed9c29e3fa5b07aa5c81749589b1170d3b85a84331e2f6b8e26eadebfd569b225759f40bbd12d6c3d253ed3f379b014b2ea44cce54d362072e2d020ff139a903b7d87fc3fddc2e6657c83e0b79851c22c6e0e477463463c97d6cc0e2e2de5e35b227bddb285521be3766358abaf3159d89f68c9770e28278f177088cfc4089b817effaaecabdffa4e66427868b105cb9348ea2d84eeea059a5d1ff3277d6f9cf656fc973d07cabed70fb8f8eb2798a65d207a8e1f8a26910949db9fa62d62bc15ecc097a93a27a1873405b8589a4ddf0ecf0303c6031484562b32eb7881975026524d6d4a9de6cd73fe2c324501586b9b6fa6bce950bbd21472278302f83dbfd6be036f2fc36d299d66578e844be3d6aa8314fab468f038fd6e130ada0a886fccfb2fd843f7dd07e8968401bbe2af7345fce52ba4b310b30af2d54b15669d06c206682c1730ab6b17787e361f04401f78dc5cbd5fac955df4e83c24cdabfabdb3f4ea40961d04a5ca166c17694fca144025b47131a68ddb230d36fe6e831e82624c9a925d706bff86982852b26ebf019a3f6ee36aedbbc6bec2d50531a233e09225493d3c5fd48379aec373baf622fb9feed6261e5296e5ae6601e7523c7f386801ed63a344b07106a0d03e5848209db5e114c0e67884916a43a1bfb77d9b8ea113c3ba8cad4b006aafeadcc31e70e85c5efecaf807154d011c1413340d4b592d2f270fb48b2050e08493c1427ddfac8dcc27fe434d32a35dcbddbcb1c4e22ead6734a4ac910f6768bc9ff6b355c1151695e41121cdcc9d9d3b18cf4d66ca3c1db0527c471a0dcf256590602a7269dcb26175e7eb370bd9794ac8ab558bea69e6a92d8e818b675a80e2df0516b8307291d93cb85d959ac60d47b46455a7ab0a38687c747c6d2d9e8c20ccf74dc6cdf145ec06805d4ac24a39aec2f5cd6e26e63e3d043a31c42411e4"; + + vm.startPrank(operator); + stakingContract.registerValidators(10, publicKeys, signatures); vm.stopPrank(); } function testReinitialization() public { vm.expectRevert(abi.encodeWithSignature("AlreadyInitialized()")); - stakingContract.initialize_1(admin, 0.1 ether, address(depositContract), withdrawalCredentials); + stakingContract.initialize_1(operator, address(depositContract), withdrawalCredentials); } - function testRegisterKeysUnauthorized() public { - bytes[] memory publicKeys = new bytes[](1); - publicKeys[ - 0 - ] = hex"24a2e06ab1fab73c784748836c9e823f67de868a5d03442bab73d2d942a5692bcdca0c228facc1506894ee3233a6c4a3"; - - bytes[] memory signatures = new bytes[](1); - signatures[ - 0 - ] = hex"e61d84053b75b684fa2bb180d28c7bf5258d96cf231686a36a61d58f37457064d405efd90db74b0c84b18fc48e57542726b1a73b631619717f9a7de162a33d1de7e96750cda2f632417f331ba5bb6441a3123151d82f4fd2793655af14904601"; - - vm.expectRevert(abi.encodeWithSignature("Unauthorized()")); - stakingContract.registerValidatorKeys(publicKeys, signatures); + function testRemove5Validators() public { + uint256[] memory indexes = new uint256[](5); + indexes[0] = 9; + indexes[1] = 8; + indexes[2] = 7; + indexes[3] = 6; + indexes[4] = 5; + assert(stakingContract.totalValidatorCount() == 10); + assert(stakingContract.fundedValidatorsCount() == 0); + vm.startPrank(operator); + startMeasuringGas("removeValidators() 5 validators"); + stakingContract.removeValidators(indexes); + stopMeasuringGas(); + vm.stopPrank(); + assert(stakingContract.totalValidatorCount() == 5); + assert(stakingContract.fundedValidatorsCount() == 0); } - function testRegisterKeys() public { - bytes[] memory publicKeys = new bytes[](1); - publicKeys[ - 0 - ] = hex"24a2e06ab1fab73c784748836c9e823f67de868a5d03442bab73d2d942a5692bcdca0c228facc1506894ee3233a6c4a3"; - - bytes[] memory signatures = new bytes[](1); - signatures[ - 0 - ] = hex"e61d84053b75b684fa2bb180d28c7bf5258d96cf231686a36a61d58f37457064d405efd90db74b0c84b18fc48e57542726b1a73b631619717f9a7de162a33d1de7e96750cda2f632417f331ba5bb6441a3123151d82f4fd2793655af14904601"; - - assert(stakingContract.getKeyCount() == 10); - vm.startPrank(admin); + function testRemove5ValidatorsFromMiddle() public { + uint256[] memory indexes = new uint256[](5); + indexes[0] = 4; + indexes[1] = 3; + indexes[2] = 2; + indexes[3] = 1; + indexes[4] = 0; + assert(stakingContract.totalValidatorCount() == 10); + assert(stakingContract.fundedValidatorsCount() == 0); + vm.startPrank(operator); + startMeasuringGas("removeValidators() 5 validators"); + stakingContract.removeValidators(indexes); + stopMeasuringGas(); + vm.stopPrank(); + assert(stakingContract.totalValidatorCount() == 5); + assert(stakingContract.fundedValidatorsCount() == 0); + } - startMeasuringGas("registerValidatorKeys(bytes[],bytes[])"); - stakingContract.registerValidatorKeys(publicKeys, signatures); + function testRemove10Validators() public { + uint256[] memory indexes = new uint256[](10); + indexes[0] = 9; + indexes[1] = 8; + indexes[2] = 7; + indexes[3] = 6; + indexes[4] = 5; + indexes[5] = 4; + indexes[6] = 3; + indexes[7] = 2; + indexes[8] = 1; + indexes[9] = 0; + assert(stakingContract.totalValidatorCount() == 10); + assert(stakingContract.fundedValidatorsCount() == 0); + vm.startPrank(operator); + startMeasuringGas("removeValidators() 10 validators"); + stakingContract.removeValidators(indexes); stopMeasuringGas(); + vm.stopPrank(); + assert(stakingContract.totalValidatorCount() == 0); + assert(stakingContract.fundedValidatorsCount() == 0); + } + function testRemoveValidatorsUnsorted() public { + uint256[] memory indexes = new uint256[](5); + indexes[0] = 5; + indexes[1] = 6; + indexes[2] = 7; + indexes[3] = 8; + indexes[4] = 9; + vm.startPrank(operator); + vm.expectRevert(abi.encodeWithSignature("UnsortedIndexes()")); + stakingContract.removeValidators(indexes); vm.stopPrank(); - assert(stakingContract.getKeyCount() == 11); } - function testRegisterKeysInvalidPublicKey() public { - bytes[] memory publicKeys = new bytes[](1); - publicKeys[ - 0 - ] = hex"24a2e06ab1fab73c784748836c9e823f67de868a5d03442bab73d2d942a5692bcdca0c228facc1506894ee3233a6c4"; + function testRemoveValidatorsFunded() public { + address(stakingContract).call{value: 32 ether}(""); + uint256[] memory indexes = new uint256[](1); + indexes[0] = 0; + assert(stakingContract.fundedValidatorsCount() == 1); + vm.startPrank(operator); + vm.expectRevert(abi.encodeWithSignature("FundedValidatorDeletionAttempt()")); + stakingContract.removeValidators(indexes); + vm.stopPrank(); + } - bytes[] memory signatures = new bytes[](1); - signatures[ - 0 - ] = hex"e61d84053b75b684fa2bb180d28c7bf5258d96cf231686a36a61d58f37457064d405efd90db74b0c84b18fc48e57542726b1a73b631619717f9a7de162a33d1de7e96750cda2f632417f331ba5bb6441a3123151d82f4fd2793655af14904601"; + function testRemoveZeroValidators() public { + uint256[] memory indexes = new uint256[](0); + vm.startPrank(operator); + vm.expectRevert(abi.encodeWithSignature("InvalidArgument()")); + stakingContract.removeValidators(indexes); + vm.stopPrank(); + } - assert(stakingContract.getKeyCount() == 10); - vm.startPrank(admin); + function testRegisterKeysUnauthorized() public { + bytes + memory publicKeys = hex"24a2e06ab1fab73c784748836c9e823f67de868a5d03442bab73d2d942a5692bcdca0c228facc1506894ee3233a6c4a3"; + bytes + memory signatures = hex"e61d84053b75b684fa2bb180d28c7bf5258d96cf231686a36a61d58f37457064d405efd90db74b0c84b18fc48e57542726b1a73b631619717f9a7de162a33d1de7e96750cda2f632417f331ba5bb6441a3123151d82f4fd2793655af14904601"; - vm.expectRevert(abi.encodeWithSignature("InvalidArgument()")); - stakingContract.registerValidatorKeys(publicKeys, signatures); + vm.expectRevert(abi.encodeWithSignature("Unauthorized()")); + stakingContract.registerValidators(1, publicKeys, signatures); } - function testRegisterKeysInvalidSignature() public { - bytes[] memory publicKeys = new bytes[](1); - publicKeys[ - 0 - ] = hex"24a2e06ab1fab73c784748836c9e823f67de868a5d03442bab73d2d942a5692bcdca0c228facc1506894ee3233a6c4a3"; + function testRegisterKeys() public { + bytes + memory publicKeys = hex"24a2e06ab1fab73c784748836c9e823f67de868a5d03442bab73d2d942a5692bcdca0c228facc1506894ee3233a6c4a3"; + bytes + memory signatures = hex"e61d84053b75b684fa2bb180d28c7bf5258d96cf231686a36a61d58f37457064d405efd90db74b0c84b18fc48e57542726b1a73b631619717f9a7de162a33d1de7e96750cda2f632417f331ba5bb6441a3123151d82f4fd2793655af14904601"; - bytes[] memory signatures = new bytes[](1); - signatures[ - 0 - ] = hex"e61d84053b75b684fa2bb180d28c7bf5258d96cf231686a36a61d58f37457064d405efd90db74b0c84b18fc48e57542726b1a73b631619717f9a7de162a33d1de7e96750cda2f632417f331ba5bb6441a3123151d82f4fd2793655af149046"; + assert(stakingContract.totalValidatorCount() == 10); + vm.startPrank(operator); - assert(stakingContract.getKeyCount() == 10); - vm.startPrank(admin); + startMeasuringGas("registerValidators(bytes[],bytes[])"); + stakingContract.registerValidators(1, publicKeys, signatures); + stopMeasuringGas(); - vm.expectRevert(abi.encodeWithSignature("InvalidArgument()")); - stakingContract.registerValidatorKeys(publicKeys, signatures); + vm.stopPrank(); + assert(stakingContract.totalValidatorCount() == 11); } - function testRegisterKeysInvalidSignatureArrayLength() public { - bytes[] memory publicKeys = new bytes[](1); - publicKeys[ - 0 - ] = hex"24a2e06ab1fab73c784748836c9e823f67de868a5d03442bab73d2d942a5692bcdca0c228facc1506894ee3233a6c4a3"; - - bytes[] memory signatures = new bytes[](2); - signatures[ - 0 - ] = hex"e61d84053b75b684fa2bb180d28c7bf5258d96cf231686a36a61d58f37457064d405efd90db74b0c84b18fc48e57542726b1a73b631619717f9a7de162a33d1de7e96750cda2f632417f331ba5bb6441a3123151d82f4fd2793655af14904601"; - signatures[ - 1 - ] = hex"2fc71d4bec4f87c108c09a98ac9bbb6203ed2208019d7a00128f494d47b4b6e77136decf1b804561bbc2e41339648ffe7304f48ed249edeca2c9238f5f5e7091be579cb62d6acb60e988749fc500196b461aa07f3fe0e2a2681f0dd4344c51ff"; + function testRegisterKeysInvalidPublicKey() public { + bytes + memory publicKeys = hex"24a2e06ab1fab73c784748836c9e823f67de868a5d03442bab73d2d942a5692bcdca0c228facc1506894ee3233a6c4"; + bytes + memory signatures = hex"e61d84053b75b684fa2bb180d28c7bf5258d96cf231686a36a61d58f37457064d405efd90db74b0c84b18fc48e57542726b1a73b631619717f9a7de162a33d1de7e96750cda2f632417f331ba5bb6441a3123151d82f4fd2793655af14904601"; - assert(stakingContract.getKeyCount() == 10); - vm.startPrank(admin); + assert(stakingContract.totalValidatorCount() == 10); + vm.startPrank(operator); - vm.expectRevert(abi.encodeWithSignature("InvalidArgument()")); - stakingContract.registerValidatorKeys(publicKeys, signatures); + vm.expectRevert(abi.encodeWithSignature("InvalidPublicKeys()")); + stakingContract.registerValidators(1, publicKeys, signatures); } - function testRegisterKeysInvalidPublicKeyArrayLength() public { - bytes[] memory publicKeys = new bytes[](2); - publicKeys[ - 0 - ] = hex"24a2e06ab1fab73c784748836c9e823f67de868a5d03442bab73d2d942a5692bcdca0c228facc1506894ee3233a6c4a3"; - publicKeys[ - 1 - ] = hex"e0a8bf46aba4e979f97eb5534f0bae149f9d5f2b36c9bb7c2b5cb140799d6aebd57de9c9401a2fea4e90e139a9f05308"; + function testRegisterKeysInvalidSignature() public { + bytes + memory publicKeys = hex"24a2e06ab1fab73c784748836c9e823f67de868a5d03442bab73d2d942a5692bcdca0c228facc1506894ee3233a6c4a3"; - bytes[] memory signatures = new bytes[](1); - signatures[ - 0 - ] = hex"e61d84053b75b684fa2bb180d28c7bf5258d96cf231686a36a61d58f37457064d405efd90db74b0c84b18fc48e57542726b1a73b631619717f9a7de162a33d1de7e96750cda2f632417f331ba5bb6441a3123151d82f4fd2793655af14904601"; + bytes + memory signatures = hex"e61d84053b75b684fa2bb180d28c7bf5258d96cf231686a36a61d58f37457064d405efd90db74b0c84b18fc48e57542726b1a73b631619717f9a7de162a33d1de7e96750cda2f632417f331ba5bb6441a3123151d82f4fd2793655af149046"; - assert(stakingContract.getKeyCount() == 10); - vm.startPrank(admin); + assert(stakingContract.totalValidatorCount() == 10); + vm.startPrank(operator); - vm.expectRevert(abi.encodeWithSignature("InvalidArgument()")); - stakingContract.registerValidatorKeys(publicKeys, signatures); + vm.expectRevert(abi.encodeWithSignature("InvalidSignatures()")); + stakingContract.registerValidators(1, publicKeys, signatures); } - function testRegisterKeysEmptyArrays() public { - bytes[] memory publicKeys = new bytes[](0); + function testRegisterKeysEmptyBytes() public { + bytes memory publicKeys = hex""; - bytes[] memory signatures = new bytes[](0); + bytes memory signatures = hex""; - assert(stakingContract.getKeyCount() == 10); - vm.startPrank(admin); + assert(stakingContract.totalValidatorCount() == 10); + vm.startPrank(operator); - vm.expectRevert(abi.encodeWithSignature("InvalidArgument()")); - stakingContract.registerValidatorKeys(publicKeys, signatures); + vm.expectRevert(abi.encodeWithSignature("InvalidPublicKeys()")); + stakingContract.registerValidators(1, publicKeys, signatures); } - function testChangingFee() public { - assertEq(stakingContract.getFee(), 0.1 ether); - vm.startPrank(admin); - startMeasuringGas("setFee"); - stakingContract.setFee(0.2 ether); - stopMeasuringGas(); - vm.stopPrank(); - assertEq(stakingContract.getFee(), 0.2 ether); - } + function testRegisterKeysZeroCount() public { + bytes memory publicKeys = hex""; - function testChangingFeeUnauthorized() public { - vm.expectRevert(abi.encodeWithSignature("Unauthorized()")); - stakingContract.setFee(0.2 ether); + bytes memory signatures = hex""; + + assert(stakingContract.totalValidatorCount() == 10); + vm.startPrank(operator); + + vm.expectRevert(abi.encodeWithSignature("InvalidArgument()")); + stakingContract.registerValidators(0, publicKeys, signatures); } function testDepositInvalidValueViaImplicitCall() public { - vm.deal(bob, 32 ether); + vm.deal(bob, 31.9 ether); vm.startPrank(bob); - vm.expectRevert(abi.encodeWithSignature("InvalidValue()")); - address(stakingContract).call{value: 32 ether}(""); + vm.expectRevert(abi.encodeWithSignature("InvalidMessageValue()")); + address(stakingContract).call{value: 31.9 ether}(""); vm.stopPrank(); } function testDepositOneValidatorViaImplicitCall() public { - vm.deal(bob, 32 ether + 0.1 ether); + vm.deal(bob, 32 ether); vm.startPrank(bob); - assert(stakingContract.getKeyCount() == 10); - assert(stakingContract.getValidatorCount() == 0); + assert(stakingContract.totalValidatorCount() == 10); + assert(stakingContract.fundedValidatorsCount() == 0); assert( stakingContract.getWithdrawer( hex"21d2e725aef3a8f9e09d8f4034948bb7f79505fc7c40e7a7ca15734bad4220a594bf0c6257cef7db88d9fc3fd4360759" ) == address(0) ); startMeasuringGas("receive() 1 validator"); - (bool ok, ) = address(stakingContract).call{value: 32 ether + 0.1 ether}(""); + (bool ok, ) = address(stakingContract).call{value: 32 ether}(""); stopMeasuringGas(); assert(ok == true); - assert(stakingContract.getKeyCount() == 10); - assert(stakingContract.getValidatorCount() == 1); + assert(stakingContract.totalValidatorCount() == 10); + assert(stakingContract.fundedValidatorsCount() == 1); assert( stakingContract.getWithdrawer( hex"21d2e725aef3a8f9e09d8f4034948bb7f79505fc7c40e7a7ca15734bad4220a594bf0c6257cef7db88d9fc3fd4360759" @@ -308,11 +277,11 @@ contract StakingContractTest is DSTestPlus { } function testDepositTenValidatorViaImplicitCall() public { - vm.deal(bob, (32 ether + 0.1 ether) * 10); + vm.deal(bob, 32 ether * 10); vm.startPrank(bob); - assert(stakingContract.getKeyCount() == 10); - assert(stakingContract.getValidatorCount() == 0); + assert(stakingContract.totalValidatorCount() == 10); + assert(stakingContract.fundedValidatorsCount() == 0); assert( stakingContract.getWithdrawer( hex"21d2e725aef3a8f9e09d8f4034948bb7f79505fc7c40e7a7ca15734bad4220a594bf0c6257cef7db88d9fc3fd4360759" @@ -365,12 +334,12 @@ contract StakingContractTest is DSTestPlus { ); startMeasuringGas("receive() 10 validators"); - (bool ok, ) = address(stakingContract).call{value: (32 ether + 0.1 ether) * 10}(""); + (bool ok, ) = address(stakingContract).call{value: 32 ether * 10}(""); stopMeasuringGas(); assert(ok == true); - assert(stakingContract.getKeyCount() == 10); - assert(stakingContract.getValidatorCount() == 10); + assert(stakingContract.totalValidatorCount() == 10); + assert(stakingContract.fundedValidatorsCount() == 10); assert( stakingContract.getWithdrawer( hex"21d2e725aef3a8f9e09d8f4034948bb7f79505fc7c40e7a7ca15734bad4220a594bf0c6257cef7db88d9fc3fd4360759" @@ -426,20 +395,20 @@ contract StakingContractTest is DSTestPlus { } function testDepositElevenValidatorViaImplicitCall() public { - vm.deal(bob, (32 ether + 0.1 ether) * 11); + vm.deal(bob, 32 ether * 11); vm.startPrank(bob); - assert(stakingContract.getKeyCount() == 10); - assert(stakingContract.getValidatorCount() == 0); + assert(stakingContract.totalValidatorCount() == 10); + assert(stakingContract.fundedValidatorsCount() == 0); vm.expectRevert(abi.encodeWithSignature("NotEnoughKeys()")); - address(stakingContract).call{value: (32 ether + 0.1 ether) * 11}(""); + address(stakingContract).call{value: 32 ether * 11}(""); } function testDepositFiveValidatorsTwiceViaImplicitCall() public { - vm.deal(bob, (32 ether + 0.1 ether) * 10); + vm.deal(bob, 32 ether * 10); vm.startPrank(bob); - assert(stakingContract.getKeyCount() == 10); - assert(stakingContract.getValidatorCount() == 0); + assert(stakingContract.totalValidatorCount() == 10); + assert(stakingContract.fundedValidatorsCount() == 0); assert( stakingContract.getWithdrawer( hex"21d2e725aef3a8f9e09d8f4034948bb7f79505fc7c40e7a7ca15734bad4220a594bf0c6257cef7db88d9fc3fd4360759" @@ -492,12 +461,12 @@ contract StakingContractTest is DSTestPlus { ); startMeasuringGas("receive() 5 validators"); - (bool ok, ) = address(stakingContract).call{value: (32 ether + 0.1 ether) * 5}(""); + (bool ok, ) = address(stakingContract).call{value: 32 ether * 5}(""); stopMeasuringGas(); assert(ok == true); - assert(stakingContract.getKeyCount() == 10); - assert(stakingContract.getValidatorCount() == 5); + assert(stakingContract.totalValidatorCount() == 10); + assert(stakingContract.fundedValidatorsCount() == 5); assert( stakingContract.getWithdrawer( hex"21d2e725aef3a8f9e09d8f4034948bb7f79505fc7c40e7a7ca15734bad4220a594bf0c6257cef7db88d9fc3fd4360759" @@ -550,12 +519,12 @@ contract StakingContractTest is DSTestPlus { ); startMeasuringGas("receive() 5 validators"); - (ok, ) = address(stakingContract).call{value: (32 ether + 0.1 ether) * 5}(""); + (ok, ) = address(stakingContract).call{value: 32 ether * 5}(""); stopMeasuringGas(); assert(ok == true); - assert(stakingContract.getKeyCount() == 10); - assert(stakingContract.getValidatorCount() == 10); + assert(stakingContract.totalValidatorCount() == 10); + assert(stakingContract.fundedValidatorsCount() == 10); assert( stakingContract.getWithdrawer( hex"21d2e725aef3a8f9e09d8f4034948bb7f79505fc7c40e7a7ca15734bad4220a594bf0c6257cef7db88d9fc3fd4360759" @@ -611,28 +580,28 @@ contract StakingContractTest is DSTestPlus { } function testDepositInvalidValueViaExplicitCall() public { - vm.deal(bob, 32 ether); + vm.deal(bob, 31.9 ether); vm.startPrank(bob); - vm.expectRevert(abi.encodeWithSignature("InvalidValue()")); - stakingContract.deposit{value: 32 ether}(bob); + vm.expectRevert(abi.encodeWithSignature("InvalidMessageValue()")); + stakingContract.deposit{value: 31.9 ether}(bob); vm.stopPrank(); } function testDepositOneValidatorViaExplicitCall() public { - vm.deal(bob, 32 ether + 0.1 ether); + vm.deal(bob, 32 ether); vm.startPrank(bob); - assert(stakingContract.getKeyCount() == 10); - assert(stakingContract.getValidatorCount() == 0); + assert(stakingContract.totalValidatorCount() == 10); + assert(stakingContract.fundedValidatorsCount() == 0); assert( stakingContract.getWithdrawer( hex"21d2e725aef3a8f9e09d8f4034948bb7f79505fc7c40e7a7ca15734bad4220a594bf0c6257cef7db88d9fc3fd4360759" ) == address(0) ); startMeasuringGas("deposit(address) 1 validator"); - stakingContract.deposit{value: 32 ether + 0.1 ether}(alice); + stakingContract.deposit{value: 32 ether}(alice); stopMeasuringGas(); - assert(stakingContract.getKeyCount() == 10); - assert(stakingContract.getValidatorCount() == 1); + assert(stakingContract.totalValidatorCount() == 10); + assert(stakingContract.fundedValidatorsCount() == 1); assert( stakingContract.getWithdrawer( hex"21d2e725aef3a8f9e09d8f4034948bb7f79505fc7c40e7a7ca15734bad4220a594bf0c6257cef7db88d9fc3fd4360759" @@ -642,11 +611,11 @@ contract StakingContractTest is DSTestPlus { } function testDepositTenValidatorViaExplicitCall() public { - vm.deal(bob, (32 ether + 0.1 ether) * 10); + vm.deal(bob, 32 ether * 10); vm.startPrank(bob); - assert(stakingContract.getKeyCount() == 10); - assert(stakingContract.getValidatorCount() == 0); + assert(stakingContract.totalValidatorCount() == 10); + assert(stakingContract.fundedValidatorsCount() == 0); assert( stakingContract.getWithdrawer( hex"21d2e725aef3a8f9e09d8f4034948bb7f79505fc7c40e7a7ca15734bad4220a594bf0c6257cef7db88d9fc3fd4360759" @@ -699,11 +668,11 @@ contract StakingContractTest is DSTestPlus { ); startMeasuringGas("deposit(address) 10 validators"); - stakingContract.deposit{value: (32 ether + 0.1 ether) * 10}(alice); + stakingContract.deposit{value: 32 ether * 10}(alice); stopMeasuringGas(); - assert(stakingContract.getKeyCount() == 10); - assert(stakingContract.getValidatorCount() == 10); + assert(stakingContract.totalValidatorCount() == 10); + assert(stakingContract.fundedValidatorsCount() == 10); assert( stakingContract.getWithdrawer( hex"21d2e725aef3a8f9e09d8f4034948bb7f79505fc7c40e7a7ca15734bad4220a594bf0c6257cef7db88d9fc3fd4360759" @@ -759,20 +728,20 @@ contract StakingContractTest is DSTestPlus { } function testDepositElevenValidatorViaExplicitCall() public { - vm.deal(bob, (32 ether + 0.1 ether) * 11); + vm.deal(bob, 32 ether * 11); vm.startPrank(bob); - assert(stakingContract.getKeyCount() == 10); - assert(stakingContract.getValidatorCount() == 0); + assert(stakingContract.totalValidatorCount() == 10); + assert(stakingContract.fundedValidatorsCount() == 0); vm.expectRevert(abi.encodeWithSignature("NotEnoughKeys()")); - stakingContract.deposit{value: (32 ether + 0.1 ether) * 11}(alice); + stakingContract.deposit{value: 32 ether * 11}(alice); } function testDepositFiveValidatorsTwiceViaExplicitCall() public { - vm.deal(bob, (32 ether + 0.1 ether) * 10); + vm.deal(bob, 32 ether * 10); vm.startPrank(bob); - assert(stakingContract.getKeyCount() == 10); - assert(stakingContract.getValidatorCount() == 0); + assert(stakingContract.totalValidatorCount() == 10); + assert(stakingContract.fundedValidatorsCount() == 0); assert( stakingContract.getWithdrawer( hex"21d2e725aef3a8f9e09d8f4034948bb7f79505fc7c40e7a7ca15734bad4220a594bf0c6257cef7db88d9fc3fd4360759" @@ -825,11 +794,11 @@ contract StakingContractTest is DSTestPlus { ); startMeasuringGas("deposit(address) 5 validators"); - stakingContract.deposit{value: (32 ether + 0.1 ether) * 5}(alice); + stakingContract.deposit{value: 32 ether * 5}(alice); stopMeasuringGas(); - assert(stakingContract.getKeyCount() == 10); - assert(stakingContract.getValidatorCount() == 5); + assert(stakingContract.totalValidatorCount() == 10); + assert(stakingContract.fundedValidatorsCount() == 5); assert( stakingContract.getWithdrawer( hex"21d2e725aef3a8f9e09d8f4034948bb7f79505fc7c40e7a7ca15734bad4220a594bf0c6257cef7db88d9fc3fd4360759" @@ -882,11 +851,11 @@ contract StakingContractTest is DSTestPlus { ); startMeasuringGas("deposit(address) 5 validators"); - stakingContract.deposit{value: (32 ether + 0.1 ether) * 5}(bob); + stakingContract.deposit{value: 32 ether * 5}(bob); stopMeasuringGas(); - assert(stakingContract.getKeyCount() == 10); - assert(stakingContract.getValidatorCount() == 10); + assert(stakingContract.totalValidatorCount() == 10); + assert(stakingContract.fundedValidatorsCount() == 10); assert( stakingContract.getWithdrawer( hex"21d2e725aef3a8f9e09d8f4034948bb7f79505fc7c40e7a7ca15734bad4220a594bf0c6257cef7db88d9fc3fd4360759" @@ -942,9 +911,9 @@ contract StakingContractTest is DSTestPlus { } function testChangeWithdrawer() public { - vm.deal(bob, 32 ether + 0.1 ether); + vm.deal(bob, 32 ether); vm.startPrank(bob); - stakingContract.deposit{value: 32 ether + 0.1 ether}(bob); + stakingContract.deposit{value: 32 ether}(bob); assert( stakingContract.getWithdrawer( hex"21d2e725aef3a8f9e09d8f4034948bb7f79505fc7c40e7a7ca15734bad4220a594bf0c6257cef7db88d9fc3fd4360759" @@ -965,9 +934,9 @@ contract StakingContractTest is DSTestPlus { } function testChangeWithdrawerUnauthorized() public { - vm.deal(bob, 32 ether + 0.1 ether); + vm.deal(bob, 32 ether); vm.startPrank(bob); - stakingContract.deposit{value: 32 ether + 0.1 ether}(alice); + stakingContract.deposit{value: 32 ether}(alice); assert( stakingContract.getWithdrawer( hex"21d2e725aef3a8f9e09d8f4034948bb7f79505fc7c40e7a7ca15734bad4220a594bf0c6257cef7db88d9fc3fd4360759"