From d6bc37bc6386227bc90e7e48e1e41dc9a8a6cf3a Mon Sep 17 00:00:00 2001 From: Mikers Date: Fri, 10 Jan 2025 14:13:34 -1000 Subject: [PATCH 1/8] Add validation to prevent uint32 truncation in readUInt32 --- contracts/v0.8/utils/CborDecode.sol | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contracts/v0.8/utils/CborDecode.sol b/contracts/v0.8/utils/CborDecode.sol index 8595989e..7f6f469a 100644 --- a/contracts/v0.8/utils/CborDecode.sol +++ b/contracts/v0.8/utils/CborDecode.sol @@ -237,6 +237,9 @@ library CBORDecoder { (maj, value, byteIdx) = parseCborHeader(cborData, byteIdx); require(maj == MajUnsignedInt, "invalid maj (expected MajUnsignedInt)"); + // Validation to prevent truncation + require(value <= type(uint32).max, "value exceeds uint32 max limit"); + return (uint32(value), byteIdx); } From 9bf881793501701b01ee28d42ac7d09ae67de7bf Mon Sep 17 00:00:00 2001 From: Mikers Date: Fri, 10 Jan 2025 14:20:38 -1000 Subject: [PATCH 2/8] Add input validation for BigInt sign byte in deserialization --- contracts/v0.8/cbor/BigIntCbor.sol | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contracts/v0.8/cbor/BigIntCbor.sol b/contracts/v0.8/cbor/BigIntCbor.sol index 0fbca392..06df8827 100644 --- a/contracts/v0.8/cbor/BigIntCbor.sol +++ b/contracts/v0.8/cbor/BigIntCbor.sol @@ -49,6 +49,9 @@ library BigIntCBOR { return CommonTypes.BigInt(hex"00", false); } + // Validate the sign byte + require(raw[0] == 0x00 || raw[0] == 0x01, "Invalid sign byte: must be 0x00 or 0x01"); + bytes memory val = new bytes(raw.length - 1); bool neg = false; From 1eabac47561da1740dbe324fbe3252032e968684 Mon Sep 17 00:00:00 2001 From: Mikers Date: Fri, 10 Jan 2025 14:25:35 -1000 Subject: [PATCH 3/8] Add strict array length check in GetDealDataCommitmentReturn deserialization --- contracts/v0.8/cbor/MarketCbor.sol | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/contracts/v0.8/cbor/MarketCbor.sol b/contracts/v0.8/cbor/MarketCbor.sol index 9e16ba4c..2af4dc96 100644 --- a/contracts/v0.8/cbor/MarketCbor.sol +++ b/contracts/v0.8/cbor/MarketCbor.sol @@ -88,7 +88,10 @@ library MarketCBOR { (len, byteIdx) = rawResp.readFixedArray(byteIdx); - if (len > 0) { + // Ensure the array length is exactly 2 or 0 + require(len == 2 || len == 0, "Invalid array length: must be 0 or 2"); + + if (len == 2) { (ret.data, byteIdx) = rawResp.readBytes(byteIdx); (ret.size, byteIdx) = rawResp.readUInt64(byteIdx); } else { From 14d60cec55dadbe6ce65d42337a1cbd872daabca Mon Sep 17 00:00:00 2001 From: Mikers Date: Fri, 10 Jan 2025 14:28:55 -1000 Subject: [PATCH 4/8] Fix capacity miscalculation in serializeExtendClaimTermsParams --- contracts/v0.8/cbor/VerifRegCbor.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/v0.8/cbor/VerifRegCbor.sol b/contracts/v0.8/cbor/VerifRegCbor.sol index 16df59be..f5c5e810 100644 --- a/contracts/v0.8/cbor/VerifRegCbor.sol +++ b/contracts/v0.8/cbor/VerifRegCbor.sol @@ -205,6 +205,7 @@ library VerifRegCBOR { capacity += Misc.getPrefixSize(1); capacity += Misc.getPrefixSize(termsLen); for (uint i = 0; i < termsLen; i++) { + capacity += Misc.getPrefixSize(3); capacity += Misc.getFilActorIdSize(terms[i].provider); capacity += Misc.getFilActorIdSize(terms[i].claim_id); capacity += Misc.getChainEpochSize(terms[i].term_max); From 09f2f205d7883ef378f8dff207718ce0cf7e1a96 Mon Sep 17 00:00:00 2001 From: Mikers Date: Mon, 13 Jan 2025 14:13:18 -1000 Subject: [PATCH 5/8] Fix: Standardize BigInt deserialization with deserializeBytesBigInt across CBOR contracts --- contracts/v0.8/cbor/MarketCbor.sol | 13 ++++++++----- contracts/v0.8/cbor/MinerCbor.sol | 10 ++++++---- contracts/v0.8/cbor/PowerCbor.sol | 4 +++- contracts/v0.8/cbor/VerifRegCbor.sol | 4 +++- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/contracts/v0.8/cbor/MarketCbor.sol b/contracts/v0.8/cbor/MarketCbor.sol index 2af4dc96..927d19d7 100644 --- a/contracts/v0.8/cbor/MarketCbor.sol +++ b/contracts/v0.8/cbor/MarketCbor.sol @@ -31,12 +31,15 @@ import "../utils/CborDecode.sol"; import "./FilecoinCbor.sol"; import "./BigIntCbor.sol"; import "./FilecoinCbor.sol"; +import "./BytesCbor.sol"; /// @title This library is a set of functions meant to handle CBOR parameters serialization and return values deserialization for Market actor exported methods. /// @author Zondax AG library MarketCBOR { using CBOR for CBOR.CBORBuffer; using CBORDecoder for bytes; + using BytesCBOR for bytes; + using BigIntCBOR for *; using FilecoinCBOR for *; @@ -71,10 +74,10 @@ library MarketCBOR { assert(len == 2); (tmp, byteIdx) = rawResp.readBytes(byteIdx); - ret.balance = tmp.deserializeBigInt(); + ret.balance = tmp.deserializeBytesBigInt(); (tmp, byteIdx) = rawResp.readBytes(byteIdx); - ret.locked = tmp.deserializeBigInt(); + ret.locked = tmp.deserializeBytesBigInt(); return ret; } @@ -296,14 +299,14 @@ library MarketCBOR { bytes memory storage_price_per_epoch_bytes; (storage_price_per_epoch_bytes, byteIdx) = rawResp.readBytes(byteIdx); - ret.storage_price_per_epoch = storage_price_per_epoch_bytes.deserializeBigInt(); + ret.storage_price_per_epoch = storage_price_per_epoch_bytes.deserializeBytesBigInt(); bytes memory provider_collateral_bytes; (provider_collateral_bytes, byteIdx) = rawResp.readBytes(byteIdx); - ret.provider_collateral = provider_collateral_bytes.deserializeBigInt(); + ret.provider_collateral = provider_collateral_bytes.deserializeBytesBigInt(); bytes memory client_collateral_bytes; (client_collateral_bytes, byteIdx) = rawResp.readBytes(byteIdx); - ret.client_collateral = client_collateral_bytes.deserializeBigInt(); + ret.client_collateral = client_collateral_bytes.deserializeBytesBigInt(); } } diff --git a/contracts/v0.8/cbor/MinerCbor.sol b/contracts/v0.8/cbor/MinerCbor.sol index 2e217d6f..3324c302 100644 --- a/contracts/v0.8/cbor/MinerCbor.sol +++ b/contracts/v0.8/cbor/MinerCbor.sol @@ -23,6 +23,7 @@ import "solidity-cborutils/contracts/CBOR.sol"; import "./BigIntCbor.sol"; import "./FilecoinCbor.sol"; +import "./BytesCbor.sol"; import "../types/MinerTypes.sol"; import "../types/CommonTypes.sol"; @@ -35,6 +36,7 @@ import "../utils/Misc.sol"; library MinerCBOR { using CBOR for CBOR.CBORBuffer; using CBORDecoder for bytes; + using BytesCBOR for bytes; using BigIntCBOR for *; using FilecoinCBOR for *; @@ -101,14 +103,14 @@ library MinerCBOR { (tmp, byteIdx) = rawResp.readBytes(byteIdx); if (tmp.length > 0) { - ret.active.term.quota = tmp.deserializeBigInt(); + ret.active.term.quota = tmp.deserializeBytesBigInt(); } else { ret.active.term.quota = CommonTypes.BigInt(new bytes(0), false); } (tmp, byteIdx) = rawResp.readBytes(byteIdx); if (tmp.length > 0) { - ret.active.term.used_quota = tmp.deserializeBigInt(); + ret.active.term.used_quota = tmp.deserializeBytesBigInt(); } else { ret.active.term.used_quota = CommonTypes.BigInt(new bytes(0), false); } @@ -123,7 +125,7 @@ library MinerCBOR { (tmp, byteIdx) = rawResp.readBytes(byteIdx); if (tmp.length > 0) { - ret.proposed.new_quota = tmp.deserializeBigInt(); + ret.proposed.new_quota = tmp.deserializeBytesBigInt(); } else { ret.proposed.new_quota = CommonTypes.BigInt(new bytes(0), false); } @@ -161,7 +163,7 @@ library MinerCBOR { (epoch, byteIdx) = rawResp.readChainEpoch(byteIdx); (tmp, byteIdx) = rawResp.readBytes(byteIdx); - amount = tmp.deserializeBigInt(); + amount = tmp.deserializeBytesBigInt(); vesting_funds[i] = MinerTypes.VestingFunds(epoch, amount); } } diff --git a/contracts/v0.8/cbor/PowerCbor.sol b/contracts/v0.8/cbor/PowerCbor.sol index 81abd109..89c0a57b 100644 --- a/contracts/v0.8/cbor/PowerCbor.sol +++ b/contracts/v0.8/cbor/PowerCbor.sol @@ -26,12 +26,14 @@ import "../types/PowerTypes.sol"; import "../utils/CborDecode.sol"; import "../utils/Misc.sol"; import "./BigIntCbor.sol"; +import "./BytesCbor.sol"; /// @title This library is a set of functions meant to handle CBOR parameters serialization and return values deserialization for Power actor exported methods. /// @author Zondax AG library PowerCBOR { using CBOR for CBOR.CBORBuffer; using CBORDecoder for bytes; + using BytesCBOR for bytes; using BigIntCBOR for CommonTypes.BigInt; using BigIntCBOR for bytes; @@ -95,7 +97,7 @@ library PowerCBOR { bytes memory tmp; (tmp, byteIdx) = rawResp.readBytes(byteIdx); if (tmp.length > 0) { - ret.raw_byte_power = tmp.deserializeBigInt(); + ret.raw_byte_power = tmp.deserializeBytesBigInt(); } else { ret.raw_byte_power = CommonTypes.BigInt(new bytes(0), false); } diff --git a/contracts/v0.8/cbor/VerifRegCbor.sol b/contracts/v0.8/cbor/VerifRegCbor.sol index f5c5e810..f1b217be 100644 --- a/contracts/v0.8/cbor/VerifRegCbor.sol +++ b/contracts/v0.8/cbor/VerifRegCbor.sol @@ -29,12 +29,14 @@ import "../utils/Misc.sol"; import "./BigIntCbor.sol"; import "./FilecoinCbor.sol"; +import "./BytesCbor.sol"; /// @title This library is a set of functions meant to handle CBOR parameters serialization and return values deserialization for VerifReg actor exported methods. /// @author Zondax AG library VerifRegCBOR { using CBOR for CBOR.CBORBuffer; using CBORDecoder for bytes; + using BytesCBOR for bytes; using BigIntCBOR for *; using FilecoinCBOR for *; @@ -190,7 +192,7 @@ library VerifRegCBOR { bytes memory tmp; (tmp, byteIdx) = rawResp.readBytes(byteIdx); - ret.datacap_recovered = tmp.deserializeBigInt(); + ret.datacap_recovered = tmp.deserializeBytesBigInt(); return ret; } From ff0b38680569cb8c72d3cafa89bd7fb09dcdd929 Mon Sep 17 00:00:00 2001 From: Mikers Date: Mon, 13 Jan 2025 14:40:08 -1000 Subject: [PATCH 6/8] Fix: Revert deserializeBytesBigInt to deserializeBigInt in MarketCBOR.sol Switched back to using deserializeBigInt for balance, locked, storage_price_per_epoch, provider_collateral, and client_collateral fields to fix deserialization issues and pass all tests. --- contracts/v0.8/cbor/MarketCbor.sol | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/contracts/v0.8/cbor/MarketCbor.sol b/contracts/v0.8/cbor/MarketCbor.sol index 927d19d7..dc27af76 100644 --- a/contracts/v0.8/cbor/MarketCbor.sol +++ b/contracts/v0.8/cbor/MarketCbor.sol @@ -31,14 +31,12 @@ import "../utils/CborDecode.sol"; import "./FilecoinCbor.sol"; import "./BigIntCbor.sol"; import "./FilecoinCbor.sol"; -import "./BytesCbor.sol"; /// @title This library is a set of functions meant to handle CBOR parameters serialization and return values deserialization for Market actor exported methods. /// @author Zondax AG library MarketCBOR { using CBOR for CBOR.CBORBuffer; using CBORDecoder for bytes; - using BytesCBOR for bytes; using BigIntCBOR for *; using FilecoinCBOR for *; @@ -74,10 +72,10 @@ library MarketCBOR { assert(len == 2); (tmp, byteIdx) = rawResp.readBytes(byteIdx); - ret.balance = tmp.deserializeBytesBigInt(); + ret.balance = tmp.deserializeBigInt(); (tmp, byteIdx) = rawResp.readBytes(byteIdx); - ret.locked = tmp.deserializeBytesBigInt(); + ret.locked = tmp.deserializeBigInt(); return ret; } @@ -299,14 +297,14 @@ library MarketCBOR { bytes memory storage_price_per_epoch_bytes; (storage_price_per_epoch_bytes, byteIdx) = rawResp.readBytes(byteIdx); - ret.storage_price_per_epoch = storage_price_per_epoch_bytes.deserializeBytesBigInt(); + ret.storage_price_per_epoch = storage_price_per_epoch_bytes.deserializeBigInt(); bytes memory provider_collateral_bytes; (provider_collateral_bytes, byteIdx) = rawResp.readBytes(byteIdx); - ret.provider_collateral = provider_collateral_bytes.deserializeBytesBigInt(); + ret.provider_collateral = provider_collateral_bytes.deserializeBigInt(); bytes memory client_collateral_bytes; (client_collateral_bytes, byteIdx) = rawResp.readBytes(byteIdx); - ret.client_collateral = client_collateral_bytes.deserializeBytesBigInt(); + ret.client_collateral = client_collateral_bytes.deserializeBigInt(); } } From acf7e81ed34c76f8d2d24292f135dabe75738cea Mon Sep 17 00:00:00 2001 From: Mikers Date: Mon, 13 Jan 2025 14:45:17 -1000 Subject: [PATCH 7/8] fix: Align buffer allocation types in serializeChangeWorkerAddressParams - Replaced uint256 with uint64 for consistent buffer allocation in capacity calculation and initialization. - Added safety check to prevent array length overflow beyond uint64 limits. - Ensured proper serialization of new_control_addresses without potential truncation. Addresses buffer allocation type mismatch warning. --- contracts/v0.8/cbor/MinerCbor.sol | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/contracts/v0.8/cbor/MinerCbor.sol b/contracts/v0.8/cbor/MinerCbor.sol index 3324c302..835790ed 100644 --- a/contracts/v0.8/cbor/MinerCbor.sol +++ b/contracts/v0.8/cbor/MinerCbor.sol @@ -173,20 +173,25 @@ library MinerCBOR { /// @return cbor serialized data as bytes function serializeChangeWorkerAddressParams(MinerTypes.ChangeWorkerAddressParams memory params) internal pure returns (bytes memory) { uint256 capacity = 0; + uint64 addressCount = uint64(params.new_control_addresses.length); + + // Safety check to prevent silent truncation + require(params.new_control_addresses.length == addressCount, "Address count exceeds uint64 limit"); capacity += Misc.getPrefixSize(2); capacity += Misc.getBytesSize(params.new_worker.data); - capacity += Misc.getPrefixSize(uint256(params.new_control_addresses.length)); - for (uint64 i = 0; i < params.new_control_addresses.length; i++) { + capacity += Misc.getPrefixSize(addressCount); + + for (uint64 i = 0; i < addressCount; i++) { capacity += Misc.getBytesSize(params.new_control_addresses[i].data); } CBOR.CBORBuffer memory buf = CBOR.create(capacity); buf.startFixedArray(2); buf.writeBytes(params.new_worker.data); - buf.startFixedArray(uint64(params.new_control_addresses.length)); + buf.startFixedArray(addressCount); - for (uint64 i = 0; i < params.new_control_addresses.length; i++) { + for (uint64 i = 0; i < addressCount; i++) { buf.writeBytes(params.new_control_addresses[i].data); } From 72285939c7bd30b369817b67fc968372a70e497b Mon Sep 17 00:00:00 2001 From: Mikers Date: Mon, 13 Jan 2025 23:00:44 -1000 Subject: [PATCH 8/8] refactor: Replace assert with if + revert using custom errors - Replaced all `assert` statements with `if` checks followed by `revert` and custom errors from `Errors.sol` - Implemented specific custom errors: - `InvalidArrayLength(uint256 expected, uint256 actual)` - `InvalidBooleanType()` - `ExpectedMajorByteString()` - `ExpectedNegativeBigNumTag()` - `ExpectedLowValue27()` - Ensured proper import of `Errors.sol` across relevant CBOR modules - Preserved original indentation and code formatting for readability - Improves error handling consistency and prevents `Panic` exceptions This change aligns with Solidity best practices by using custom errors for more efficient and descriptive error handling. --- contracts/v0.8/cbor/AccountCbor.sol | 6 +++- contracts/v0.8/cbor/DataCapCbor.sol | 14 ++++++-- contracts/v0.8/cbor/FilecoinCbor.sol | 6 +++- contracts/v0.8/cbor/MarketCbor.sol | 25 ++++++++++---- contracts/v0.8/cbor/MinerCbor.sol | 29 ++++++++++++---- contracts/v0.8/cbor/PowerCbor.sol | 9 +++-- contracts/v0.8/cbor/VerifRegCbor.sol | 49 +++++++++++++++++++++------- contracts/v0.8/utils/CborDecode.sol | 18 +++++++--- contracts/v0.8/utils/Errors.sol | 7 ++++ 9 files changed, 127 insertions(+), 36 deletions(-) diff --git a/contracts/v0.8/cbor/AccountCbor.sol b/contracts/v0.8/cbor/AccountCbor.sol index 9488a543..c75fd5c2 100644 --- a/contracts/v0.8/cbor/AccountCbor.sol +++ b/contracts/v0.8/cbor/AccountCbor.sol @@ -25,6 +25,7 @@ import "../types/AccountTypes.sol"; import "../utils/CborDecode.sol"; import "../utils/Misc.sol"; +import "../utils/Errors.sol"; /// @title This library is a set of functions meant to handle CBOR parameters serialization and return values deserialization for Account actor exported methods. /// @author Zondax AG @@ -59,7 +60,10 @@ library AccountCBOR { uint len; (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 2); + if (!(len == 2)) { + revert Errors.InvalidArrayLength(2, len); + } + (ret.signature, byteIdx) = rawResp.readBytes(byteIdx); (ret.message, byteIdx) = rawResp.readBytes(byteIdx); diff --git a/contracts/v0.8/cbor/DataCapCbor.sol b/contracts/v0.8/cbor/DataCapCbor.sol index e9de9ab7..60a7e864 100644 --- a/contracts/v0.8/cbor/DataCapCbor.sol +++ b/contracts/v0.8/cbor/DataCapCbor.sol @@ -87,7 +87,10 @@ library DataCapCBOR { bytes memory tmp; (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 3); + if (!(len == 3)) { + revert Errors.InvalidArrayLength(3, len); + } + (tmp, byteIdx) = rawResp.readBytes(byteIdx); ret.from_balance = tmp.deserializeBigInt(); @@ -133,7 +136,9 @@ library DataCapCBOR { bytes memory tmp; (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 4); + if (!(len == 4)) { + revert Errors.InvalidArrayLength(4, len); + } (tmp, byteIdx) = rawResp.readBytes(byteIdx); ret.from_balance = tmp.deserializeBigInt(); @@ -217,7 +222,10 @@ library DataCapCBOR { bytes memory tmp; (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 2); + if (!(len == 2)) { + revert Errors.InvalidArrayLength(2, len); + } + (tmp, byteIdx) = rawResp.readBytes(byteIdx); ret.balance = tmp.deserializeBigInt(); diff --git a/contracts/v0.8/cbor/FilecoinCbor.sol b/contracts/v0.8/cbor/FilecoinCbor.sol index 3c8ab44d..f020a293 100644 --- a/contracts/v0.8/cbor/FilecoinCbor.sol +++ b/contracts/v0.8/cbor/FilecoinCbor.sol @@ -24,6 +24,7 @@ import "@ensdomains/buffer/contracts/Buffer.sol"; import "../utils/CborDecode.sol"; import "../utils/Misc.sol"; +import "../utils/Errors.sol"; import "../types/CommonTypes.sol"; @@ -145,7 +146,10 @@ library FilecoinCBOR { bytes memory tmp; (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 1); + if (!(len == 1)) { + revert Errors.InvalidArrayLength(1, len); + } + (tmp, byteIdx) = rawResp.readBytes(byteIdx); return tmp.deserializeBigInt(); diff --git a/contracts/v0.8/cbor/MarketCbor.sol b/contracts/v0.8/cbor/MarketCbor.sol index dc27af76..dd34c11b 100644 --- a/contracts/v0.8/cbor/MarketCbor.sol +++ b/contracts/v0.8/cbor/MarketCbor.sol @@ -25,6 +25,7 @@ import "../types/MarketTypes.sol"; import "../types/CommonTypes.sol"; import "../utils/Misc.sol"; +import "../utils/Errors.sol"; import "../utils/FilAddresses.sol"; import "../utils/CborDecode.sol"; @@ -69,7 +70,9 @@ library MarketCBOR { bytes memory tmp; (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 2); + if (!(len == 2)) { + revert Errors.InvalidArrayLength(2, len); + } (tmp, byteIdx) = rawResp.readBytes(byteIdx); ret.balance = tmp.deserializeBigInt(); @@ -111,7 +114,9 @@ library MarketCBOR { uint len; (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 2); + if (!(len == 2)) { + revert Errors.InvalidArrayLength(2, len); + } (ret.start, byteIdx) = rawResp.readChainEpoch(byteIdx); (ret.duration, byteIdx) = rawResp.readChainEpoch(byteIdx); @@ -127,7 +132,9 @@ library MarketCBOR { uint len; (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 2); + if (!(len == 2)) { + revert Errors.InvalidArrayLength(2, len); + } (ret.activated, byteIdx) = rawResp.readChainEpoch(byteIdx); (ret.terminated, byteIdx) = rawResp.readChainEpoch(byteIdx); @@ -199,7 +206,9 @@ library MarketCBOR { uint len; (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 2); + if (!(len == 2)) { + revert Errors.InvalidArrayLength(2, len); + } (len, byteIdx) = rawResp.readFixedArray(byteIdx); ret.ids = new uint64[](len); @@ -230,7 +239,9 @@ library MarketCBOR { uint len; (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 2); + if (!(len == 2)) { + revert Errors.InvalidArrayLength(2, len); + } (ret.dealProposal, byteIdx) = rawResp.readBytes(byteIdx); (ret.dealId, byteIdx) = rawResp.readUInt64(byteIdx); @@ -279,7 +290,9 @@ library MarketCBOR { bytes memory tmp; (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 11); + if (!(len == 11)) { + revert Errors.InvalidArrayLength(11, len); + } (ret.piece_cid, byteIdx) = rawResp.readCid(byteIdx); (ret.piece_size, byteIdx) = rawResp.readUInt64(byteIdx); diff --git a/contracts/v0.8/cbor/MinerCbor.sol b/contracts/v0.8/cbor/MinerCbor.sol index 835790ed..a965dd45 100644 --- a/contracts/v0.8/cbor/MinerCbor.sol +++ b/contracts/v0.8/cbor/MinerCbor.sol @@ -30,6 +30,7 @@ import "../types/CommonTypes.sol"; import "../utils/CborDecode.sol"; import "../utils/Misc.sol"; +import "../utils/Errors.sol"; /// @title This library is a set of functions meant to handle CBOR parameters serialization and return values deserialization for Miner actor exported methods. /// @author Zondax AG @@ -69,7 +70,9 @@ library MinerCBOR { uint len; (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 2); + if (!(len == 2)) { + revert Errors.InvalidArrayLength(2, len); + } (ret.owner.data, byteIdx) = rawResp.readBytes(byteIdx); @@ -91,15 +94,21 @@ library MinerCBOR { uint len; (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 2); + if (!(len == 2)) { + revert Errors.InvalidArrayLength(2, len); + } (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 2); + if (!(len == 2)) { + revert Errors.InvalidArrayLength(2, len); + } (ret.active.beneficiary.data, byteIdx) = rawResp.readBytes(byteIdx); (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 3); + if (!(len == 3)) { + revert Errors.InvalidArrayLength(3, len); + } (tmp, byteIdx) = rawResp.readBytes(byteIdx); if (tmp.length > 0) { @@ -119,7 +128,9 @@ library MinerCBOR { if (!rawResp.isNullNext(byteIdx)) { (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 5); + if (!(len == 5)) { + revert Errors.InvalidArrayLength(5, len); + } (ret.proposed.new_beneficiary.data, byteIdx) = rawResp.readBytes(byteIdx); @@ -151,7 +162,9 @@ library MinerCBOR { uint leni; (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 1); + if (len != 1) { + revert Errors.InvalidArrayLength(1, len); + } (len, byteIdx) = rawResp.readFixedArray(byteIdx); vesting_funds = new MinerTypes.VestingFunds[](len); @@ -229,7 +242,9 @@ library MinerCBOR { uint len; (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 1); + if (len != 1) { + revert Errors.InvalidArrayLength(1, len); + } (len, byteIdx) = rawResp.readFixedArray(byteIdx); multi_addrs = new CommonTypes.FilAddress[](len); diff --git a/contracts/v0.8/cbor/PowerCbor.sol b/contracts/v0.8/cbor/PowerCbor.sol index 89c0a57b..3023405a 100644 --- a/contracts/v0.8/cbor/PowerCbor.sol +++ b/contracts/v0.8/cbor/PowerCbor.sol @@ -25,6 +25,7 @@ import "../types/CommonTypes.sol"; import "../types/PowerTypes.sol"; import "../utils/CborDecode.sol"; import "../utils/Misc.sol"; +import "../utils/Errors.sol"; import "./BigIntCbor.sol"; import "./BytesCbor.sol"; @@ -76,7 +77,9 @@ library PowerCBOR { uint len; (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 2); + if (!(len == 2)) { + revert Errors.InvalidArrayLength(2, len); + } (ret.id_address.data, byteIdx) = rawResp.readBytes(byteIdx); (ret.robust_address.data, byteIdx) = rawResp.readBytes(byteIdx); @@ -92,7 +95,9 @@ library PowerCBOR { uint len; (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 2); + if (!(len == 2)) { + revert Errors.InvalidArrayLength(2, len); + } bytes memory tmp; (tmp, byteIdx) = rawResp.readBytes(byteIdx); diff --git a/contracts/v0.8/cbor/VerifRegCbor.sol b/contracts/v0.8/cbor/VerifRegCbor.sol index f1b217be..5c506dbf 100644 --- a/contracts/v0.8/cbor/VerifRegCbor.sol +++ b/contracts/v0.8/cbor/VerifRegCbor.sol @@ -26,6 +26,7 @@ import "../types/VerifRegTypes.sol"; import "../utils/CborDecode.sol"; import "../utils/Misc.sol"; +import "../utils/Errors.sol"; import "./BigIntCbor.sol"; import "./FilecoinCbor.sol"; @@ -74,10 +75,14 @@ library VerifRegCBOR { uint ilen; (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 2); + if (!(len == 2)) { + revert Errors.InvalidArrayLength(2, len); + } (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 2); + if (!(len == 2)) { + revert Errors.InvalidArrayLength(2, len); + } (ret.batch_info.success_count, byteIdx) = rawResp.readUInt32(byteIdx); @@ -86,7 +91,9 @@ library VerifRegCBOR { for (uint i = 0; i < len; i++) { (ilen, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(ilen == 2); + if (!(len == 2)) { + revert Errors.InvalidArrayLength(2, len); + } (ret.batch_info.fail_codes[i].idx, byteIdx) = rawResp.readUInt32(byteIdx); (ret.batch_info.fail_codes[i].code, byteIdx) = rawResp.readUInt32(byteIdx); @@ -97,7 +104,9 @@ library VerifRegCBOR { for (uint i = 0; i < len; i++) { (ilen, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(ilen == 8); + if (!(len == 8)) { + revert Errors.InvalidArrayLength(8, len); + } (ret.claims[i].provider, byteIdx) = rawResp.readFilActorId(byteIdx); (ret.claims[i].client, byteIdx) = rawResp.readFilActorId(byteIdx); @@ -165,7 +174,9 @@ library VerifRegCBOR { uint ilen; (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 3); + if (!(len == 3)) { + revert Errors.InvalidArrayLength(3, len); + } (len, byteIdx) = rawResp.readFixedArray(byteIdx); ret.considered = new CommonTypes.FilActorId[](len); @@ -175,7 +186,9 @@ library VerifRegCBOR { } (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 2); + if (!(len == 2)) { + revert Errors.InvalidArrayLength(2, len); + } (ret.results.success_count, byteIdx) = rawResp.readUInt32(byteIdx); @@ -184,7 +197,9 @@ library VerifRegCBOR { for (uint i = 0; i < len; i++) { (ilen, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(ilen == 2); + if (!(len == 2)) { + revert Errors.InvalidArrayLength(2, len); + } (ret.results.fail_codes[i].idx, byteIdx) = rawResp.readUInt32(byteIdx); (ret.results.fail_codes[i].code, byteIdx) = rawResp.readUInt32(byteIdx); @@ -235,7 +250,9 @@ library VerifRegCBOR { uint ilen; (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 2); + if (!(len == 2)) { + revert Errors.InvalidArrayLength(2, len); + } (ret.success_count, byteIdx) = rawResp.readUInt32(byteIdx); @@ -244,7 +261,9 @@ library VerifRegCBOR { for (uint i = 0; i < len; i++) { (ilen, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(ilen == 2); + if (!(len == 2)) { + revert Errors.InvalidArrayLength(2, len); + } (ret.fail_codes[i].idx, byteIdx) = rawResp.readUInt32(byteIdx); (ret.fail_codes[i].code, byteIdx) = rawResp.readUInt32(byteIdx); @@ -287,7 +306,9 @@ library VerifRegCBOR { uint ilen; (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 2); + if (!(len == 2)) { + revert Errors.InvalidArrayLength(2, len); + } (len, byteIdx) = rawResp.readFixedArray(byteIdx); ret.considered = new CommonTypes.FilActorId[](len); @@ -297,7 +318,9 @@ library VerifRegCBOR { } (len, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(len == 2); + if (!(len == 2)) { + revert Errors.InvalidArrayLength(2, len); + } (ret.results.success_count, byteIdx) = rawResp.readUInt32(byteIdx); @@ -306,7 +329,9 @@ library VerifRegCBOR { for (uint i = 0; i < len; i++) { (ilen, byteIdx) = rawResp.readFixedArray(byteIdx); - assert(ilen == 2); + if (!(len == 2)) { + revert Errors.InvalidArrayLength(2, len); + } (ret.results.fail_codes[i].idx, byteIdx) = rawResp.readUInt32(byteIdx); (ret.results.fail_codes[i].code, byteIdx) = rawResp.readUInt32(byteIdx); diff --git a/contracts/v0.8/utils/CborDecode.sol b/contracts/v0.8/utils/CborDecode.sol index 7f6f469a..f113a97f 100644 --- a/contracts/v0.8/utils/CborDecode.sol +++ b/contracts/v0.8/utils/CborDecode.sol @@ -18,6 +18,8 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.17; +import "./Errors.sol"; + // MajUnsignedInt = 0 // MajSignedInt = 1 // MajByteString = 2 @@ -64,7 +66,9 @@ library CBORDecoder { (maj, value, byteIdx) = parseCborHeader(cborData, byteIdx); require(maj == MajOther, "invalid maj (expected MajOther)"); - assert(value == True_Type || value == False_Type); + if (!(value == True_Type || value == False_Type)) { + revert Errors.InvalidBooleanType(); + } return (value != False_Type, byteIdx); } @@ -118,7 +122,9 @@ library CBORDecoder { if (maj == MajTag) { (maj, len, byteIdx) = parseCborHeader(cborData, byteIdx); - assert(maj == MajByteString); + if (!(maj == MajByteString)) { + revert Errors.ExpectedMajorByteString(); + } } uint max_len = byteIdx + len; @@ -195,7 +201,9 @@ library CBORDecoder { require(maj == MajTag || maj == MajSignedInt, "invalid maj (expected MajTag or MajSignedInt)"); if (maj == MajTag) { - assert(value == TagTypeNegativeBigNum); + if (!(value == TagTypeNegativeBigNum)) { + revert Errors.ExpectedNegativeBigNumTag(); + } uint len; (maj, len, byteIdx) = parseCborHeader(cborData, byteIdx); @@ -415,7 +423,9 @@ library CBORDecoder { } // extra in next 8 bytes - assert(low == 27); + if (!(low == 27)) { + revert Errors.ExpectedLowValue27(); + } uint64 extra64 = sliceUInt64(cbor, byteIndex); byteIndex += 8; return (maj, extra64, byteIndex); diff --git a/contracts/v0.8/utils/Errors.sol b/contracts/v0.8/utils/Errors.sol index 5b535e5c..c43d3328 100644 --- a/contracts/v0.8/utils/Errors.sol +++ b/contracts/v0.8/utils/Errors.sol @@ -2,6 +2,13 @@ pragma solidity ^0.8.18; library Errors { + + error InvalidArrayLength(uint256 expected, uint256 actual); + error InvalidBooleanType(); + error ExpectedMajorByteString(); + error ExpectedNegativeBigNumTag(); + error ExpectedLowValue27(); + error NonZeroExitCode(int256 exit_code, string description); // Exit codes