diff --git a/contracts/EthStorageContract.sol b/contracts/EthStorageContract.sol index 3731286..6879e54 100644 --- a/contracts/EthStorageContract.sol +++ b/contracts/EthStorageContract.sol @@ -163,6 +163,7 @@ abstract contract EthStorageContract is StorageContract, ISemver { uint256 parent = uint256(_hash0) % _rows; uint256 sampleIdx = parent + (_startShardId << (SHARD_ENTRY_BITS + SAMPLE_LEN_BITS)); uint256 kvIdx = sampleIdx >> SAMPLE_LEN_BITS; + /// forge-lint: disable-next-line(incorrect-shift) uint256 sampleIdxInKv = sampleIdx % (1 << SAMPLE_LEN_BITS); return (kvIdx, sampleIdxInKv); } diff --git a/contracts/EthStorageContractM1.sol b/contracts/EthStorageContractM1.sol index 1efe642..fb55cb7 100644 --- a/contracts/EthStorageContractM1.sol +++ b/contracts/EthStorageContractM1.sol @@ -76,6 +76,7 @@ contract EthStorageContractM1 is EthStorageContract, Decoder { } // calculate the number of samples range of the sample check + /// forge-lint: disable-next-line(incorrect-shift) uint256 rows = 1 << (SHARD_ENTRY_BITS + SAMPLE_LEN_BITS); for (uint256 i = 0; i < RANDOM_CHECKS; i++) { diff --git a/contracts/EthStorageContractM2.sol b/contracts/EthStorageContractM2.sol index 68929c2..dfc673c 100644 --- a/contracts/EthStorageContractM2.sol +++ b/contracts/EthStorageContractM2.sol @@ -111,6 +111,7 @@ contract EthStorageContractM2 is EthStorageContract, Decoder2 { } // calculate the number of samples range of the sample check + /// forge-lint: disable-next-line(incorrect-shift) uint256 rows = 1 << (SHARD_ENTRY_BITS + SAMPLE_LEN_BITS); uint256[] memory kvIdxs = new uint256[](RANDOM_CHECKS); diff --git a/contracts/StorageContract.sol b/contracts/StorageContract.sol index 9170d4e..c675e14 100644 --- a/contracts/StorageContract.sol +++ b/contracts/StorageContract.sol @@ -174,6 +174,7 @@ abstract contract StorageContract is DecentralizedKV, AccessControlUpgradeable { /// @notice Constructs the StorageContract contract. Initializes the storage config. /// @custom:oz-upgrades-unsafe-allow constructor constructor(Config memory _config, uint256 _startTime, uint256 _storageCost, uint256 _dcfFactor) + /// forge-lint: disable-next-line(incorrect-shift) DecentralizedKV(1 << _config.maxKvSizeBits, _startTime, _storageCost, _dcfFactor) { /* Assumptions */ @@ -254,6 +255,7 @@ abstract contract StorageContract is DecentralizedKV, AccessControlUpgradeable { if (_getShardId(totalEntries) > shardId) { // We assume the rate limit (e.g., block gas limit) will ensure _batchSize < (1 << SHARD_ENTRY_BITS). // i.e., at most one new shard will be created in this Tx. + /// forge-lint: disable-next-line(incorrect-shift) uint256 kvCountNew = totalEntries % (1 << SHARD_ENTRY_BITS); totalPayment += _upfrontPayment(_blockTs()) * kvCountNew; // the shard will use _blockTs() as lastMineTime (see _checkAppend()) totalPayment += _upfrontPayment($._infos[shardId].lastMineTime) * (_batchSize - kvCountNew); @@ -372,6 +374,7 @@ abstract contract StorageContract is DecentralizedKV, AccessControlUpgradeable { if (_shardId < lastShardIdx) { reward = _paymentIn(STORAGE_COST << SHARD_ENTRY_BITS, info.lastMineTime, _minedTs); } else if (_shardId == lastShardIdx) { + /// forge-lint: disable-next-line(incorrect-shift) reward = _paymentIn(STORAGE_COST * (kvEntryCount() % (1 << SHARD_ENTRY_BITS)), info.lastMineTime, _minedTs); // Additional prepaid for the last shard if ($._prepaidLastMineTime < _minedTs) { diff --git a/contracts/libraries/BinaryRelated.sol b/contracts/libraries/BinaryRelated.sol index efba112..8441195 100644 --- a/contracts/libraries/BinaryRelated.sol +++ b/contracts/libraries/BinaryRelated.sol @@ -4,6 +4,7 @@ pragma solidity 0.8.28; library BinaryRelated { function pow(uint256 fp, uint256 n) internal pure returns (uint256) { // 1.0 in Q128.128 + /// forge-lint: disable-next-line(incorrect-shift) uint256 v = 1 << 128; // we can use unchecked here because we know that fp is in the range [0, 2^128), and it can save gas if n is large unchecked { @@ -25,6 +26,7 @@ library BinaryRelated { } function reverseBits(uint256 bits, uint256 input) internal pure returns (uint256) { + /// forge-lint: disable-next-line(incorrect-shift) assert(input < (1 << bits)); uint256 n = input; uint256 r = 0; diff --git a/contracts/libraries/MerkleLib.sol b/contracts/libraries/MerkleLib.sol index 4c63d89..b13bbda 100644 --- a/contracts/libraries/MerkleLib.sol +++ b/contracts/libraries/MerkleLib.sol @@ -6,6 +6,7 @@ import "./BinaryRelated.sol"; library MerkleLib { // Calculate the Merkle root of a given data with chunk size and number of maximum chunks in the data limit. function merkleRoot(bytes memory data, uint256 chunkSize, uint256 nChunkBits) internal pure returns (bytes32) { + /// forge-lint: disable-next-line(incorrect-shift) uint256 nChunks = 1 << nChunkBits; bytes32[] memory nodes = new bytes32[](nChunks); for (uint256 i = 0; i < nChunks; i++) { @@ -81,6 +82,7 @@ library MerkleLib { { bytes32 hash = dataHash; uint256 nChunkBits = proofs.length; + /// forge-lint: disable-next-line(incorrect-shift) require(chunkIdx < (1 << nChunkBits), "chunkId overflows"); for (uint256 i = 0; i < nChunkBits; i++) { if (chunkIdx % 2 == 0) { @@ -101,6 +103,7 @@ library MerkleLib { { bytes32 hash = dataHash; uint256 nChunkBits = proofs.length; + /// forge-lint: disable-next-line(incorrect-shift) require(chunkIdx < (1 << nChunkBits), "chunkId overflows"); for (uint256 i = 0; i < nChunkBits; i++) { if (chunkIdx % 2 == 0) { @@ -119,6 +122,7 @@ library MerkleLib { pure returns (bytes32[] memory) { + /// forge-lint: disable-next-line(incorrect-shift) uint256 nChunks = 1 << nChunkBits; require(chunkIdx < nChunks, "index out of scope"); bytes32[] memory nodes = new bytes32[](nChunks); diff --git a/contracts/test/EthStorageContractM1Test.t.sol b/contracts/test/EthStorageContractM1Test.t.sol index ec628b2..2a938af 100644 --- a/contracts/test/EthStorageContractM1Test.t.sol +++ b/contracts/test/EthStorageContractM1Test.t.sol @@ -45,6 +45,7 @@ contract EthStorageContractM1Test is Test { storageContract.putBlob{value: sufficientCost}(key, blobIdx, length); assertEq(storageContract.kvEntryCount(), 1); + /// forge-lint: disable-next-line(incorrect-shift) assertEq(storageContract.hash(key), bytes32(uint256(1 << 8 * 8))); assertEq(storageContract.size(key), 10); @@ -54,6 +55,7 @@ contract EthStorageContractM1Test is Test { sufficientCost = storageContract.upfrontPayment(); storageContract.putBlob{value: sufficientCost}(key, blobIdx, length); assertEq(storageContract.kvEntryCount(), 2); + /// forge-lint: disable-next-line(incorrect-shift) assertEq(storageContract.hash(key), bytes32(uint256(1 << 8 * 8))); assertEq(storageContract.size(key), 20); } @@ -80,8 +82,10 @@ contract EthStorageContractM1Test is Test { storageContract.putBlobs{value: sufficientCost}(keys, blobIdxs, lengths); assertEq(storageContract.kvEntryCount(), 2); + /// forge-lint: disable-start(incorrect-shift) assertEq(storageContract.hash(keys[0]), bytes32(uint256(1 << 8 * 8))); assertEq(storageContract.hash(keys[1]), bytes32(uint256(2 << 8 * 8))); + /// forge-lint: disable-end(incorrect-shift) assertEq(storageContract.size(keys[0]), 10); assertEq(storageContract.size(keys[1]), 20); @@ -93,9 +97,11 @@ contract EthStorageContractM1Test is Test { sufficientCost = storageContract.upfrontPayment(); storageContract.putBlobs{value: sufficientCost}(keys, blobIdxs, lengths); assertEq(storageContract.kvEntryCount(), 3); + /// forge-lint: disable-start(incorrect-shift) assertEq(storageContract.hash(bytes32(uint256(0))), bytes32(uint256(1 << 8 * 8))); assertEq(storageContract.hash(bytes32(uint256(1))), bytes32(uint256(2 << 8 * 8))); assertEq(storageContract.hash(bytes32(uint256(2))), bytes32(uint256(2 << 8 * 8))); + /// forge-lint: disable-end(incorrect-shift) assertEq(storageContract.size(bytes32(uint256(0))), 30); assertEq(storageContract.size(bytes32(uint256(1))), 20); assertEq(storageContract.size(bytes32(uint256(2))), 30); diff --git a/contracts/test/TestEthStorageContractM1.sol b/contracts/test/TestEthStorageContractM1.sol index fa15772..e56786c 100644 --- a/contracts/test/TestEthStorageContractM1.sol +++ b/contracts/test/TestEthStorageContractM1.sol @@ -49,6 +49,7 @@ contract TestEthStorageContractM1 is EthStorageContractM1 { } function putBlob(bytes32 _key, uint256, /* _blobIdx */ uint256 _length) public payable override { + /// forge-lint: disable-next-line(incorrect-shift) bytes32 dataHash = bytes32(uint256(1 << 8 * 8)); require(dataHash != 0, "EthStorageContract: failed to get blob hash"); @@ -74,6 +75,7 @@ contract TestEthStorageContractM1 is EthStorageContractM1 { bytes32[] memory dataHashes = new bytes32[](_blobIdxs.length); for (uint256 i = 0; i < _blobIdxs.length; i++) { + /// forge-lint: disable-next-line(incorrect-shift) dataHashes[i] = bytes32(i + 1 << 8 * 8); // dummy data hash require(dataHashes[i] != 0, "EthStorageContract: failed to get blob hash"); } @@ -156,11 +158,13 @@ contract TestEthStorageContractM1 is EthStorageContractM1 { function getSampleIdx(uint256 startShardId, bytes32 hash0) public view returns (uint256, uint256, uint256) { // calculate the number of samples range of the sample check + /// forge-lint: disable-next-line(incorrect-shift) uint256 rows = 1 << (SHARD_ENTRY_BITS + SAMPLE_LEN_BITS); // kvNumbersPerShard * smapleNumersPerKV uint256 parent = uint256(hash0) % rows; uint256 sampleIdx = parent + (startShardId << (SHARD_ENTRY_BITS + SAMPLE_LEN_BITS)); uint256 kvIdx = sampleIdx >> SAMPLE_LEN_BITS; + /// forge-lint: disable-next-line(incorrect-shift) uint256 sampleIdxInKv = sampleIdx % (1 << SAMPLE_LEN_BITS); return (sampleIdx, kvIdx, sampleIdxInKv); diff --git a/foundry.toml b/foundry.toml index 2e5181b..c52bbf9 100644 --- a/foundry.toml +++ b/foundry.toml @@ -16,7 +16,3 @@ fs_permissions = [ ] optimizer = true optimizer_runs = 200 - -[lint] -severity = ["high"] -exclude_lints = ["incorrect-shift"]