@@ -15,6 +15,7 @@ import {VerifRegAPI} from "filecoin-solidity/v0.8/VerifRegAPI.sol";
1515import {UtilsHandlers} from "filecoin-solidity/v0.8/utils/UtilsHandlers.sol " ;
1616import {MinerUtils} from "./libs/MinerUtils.sol " ;
1717import {BeneficiaryFactory} from "./BeneficiaryFactory.sol " ;
18+ import {MinerTypes} from "filecoin-solidity/v0.8/types/MinerTypes.sol " ;
1819
1920/**
2021 * @title Client
@@ -140,9 +141,17 @@ contract Client is Initializable, AccessControlUpgradeable, UUPSUpgradeable {
140141 */
141142 error InvalidBeneficiary (address beneficiary , address expectedBeneficiary );
142143
144+ /**
145+ * @notice Thrown if beneficiary expiration is insufficient
146+ */
147+ error InsufficientBeneficiaryExpiration (
148+ CommonTypes.FilActorId provider , int64 beneficiaryExpiration , int128 requiredExpiration
149+ );
150+
143151 struct ProviderAllocation {
144152 CommonTypes.FilActorId provider;
145153 uint64 size;
154+ int128 allocationTime;
146155 }
147156
148157 struct ProviderClaim {
@@ -231,9 +240,13 @@ contract Client is Initializable, AccessControlUpgradeable, UUPSUpgradeable {
231240 if (failed) revert InvalidAmount ();
232241 uint256 datacapAmount = tokenAmount / TOKEN_PRECISION;
233242
234- (ProviderAllocation[] memory allocations , ProviderClaim[] memory claimExtensions ) =
235- _deserializeVerifregOperatorData (params.operator_data);
243+ (
244+ ProviderAllocation[] memory allocations ,
245+ ProviderClaim[] memory claimExtensions ,
246+ ProviderAllocation memory longestAllocation
247+ ) = _deserializeVerifregOperatorData (params.operator_data);
236248
249+ _verifyBeneficiaryExpiration (longestAllocation);
237250 _verifyAndRegisterAllocations (allocations);
238251 _verifyAndRegisterClaimExtensions (claimExtensions);
239252 emit DatacapSpent (msg .sender , datacapAmount);
@@ -328,24 +341,51 @@ contract Client is Initializable, AccessControlUpgradeable, UUPSUpgradeable {
328341 }
329342 }
330343
344+ /**
345+ * @notice Verifies that the beneficiary expiration is sufficient for the longest allocation.
346+ * @param longestAllocation The longest allocation.
347+ * @dev Reverts with InsufficientBeneficiaryExpiration if the beneficiary expiration is insufficient.
348+ */
349+ function _verifyBeneficiaryExpiration (ProviderAllocation memory longestAllocation ) internal {
350+ MinerTypes.GetBeneficiaryReturn memory beneficiary =
351+ MinerUtils.getBeneficiaryWithChecks (longestAllocation.provider, beneficiaryFactory, true , true , true );
352+ if (
353+ longestAllocation.allocationTime
354+ > int128 (CommonTypes.ChainEpoch.unwrap (beneficiary.active.term.expiration) + 180 days)
355+ ) {
356+ revert InsufficientBeneficiaryExpiration (
357+ longestAllocation.provider,
358+ CommonTypes.ChainEpoch.unwrap (beneficiary.active.term.expiration),
359+ longestAllocation.allocationTime
360+ );
361+ }
362+ }
363+
331364 // solhint-disable function-max-lines
332365 /**
333366 * @notice Deserialize Verifreg Operator Data.
334367 * @param cborData The cbor encoded operator data.
335368 * @return allocations Array of provider allocations.
336369 * @return claimExtensions Array of provider claims.
370+ * @return longestAllocation Allocation with the longest term.
337371 */
338372 function _deserializeVerifregOperatorData (bytes memory cborData )
339373 internal
340374 pure
341- returns (ProviderAllocation[] memory allocations , ProviderClaim[] memory claimExtensions )
375+ returns (
376+ ProviderAllocation[] memory allocations ,
377+ ProviderClaim[] memory claimExtensions ,
378+ ProviderAllocation memory longestAllocation
379+ )
342380 {
343381 uint256 operatorDataLength;
344382 uint256 allocationRequestsLength;
345383 uint256 claimExtensionRequestsLength;
346384 uint64 provider;
347385 uint64 claimId;
348386 uint64 size;
387+ int64 termMax;
388+ int64 expiration;
349389 uint256 byteIdx = 0 ;
350390
351391 (operatorDataLength, byteIdx) = CBORDecoder.readFixedArray (cborData, byteIdx);
@@ -366,12 +406,17 @@ contract Client is Initializable, AccessControlUpgradeable, UUPSUpgradeable {
366406 (, byteIdx) = CBORDecoder.readBytes (cborData, byteIdx); // data (CID)
367407 (size, byteIdx) = CBORDecoder.readUInt64 (cborData, byteIdx);
368408 (, byteIdx) = CBORDecoder.readInt64 (cborData, byteIdx); // termMin
369- (, byteIdx) = CBORDecoder.readInt64 (cborData, byteIdx); // termMax
370- (, byteIdx) = CBORDecoder.readInt64 (cborData, byteIdx); // expiration
409+ (termMax , byteIdx) = CBORDecoder.readInt64 (cborData, byteIdx);
410+ (expiration , byteIdx) = CBORDecoder.readInt64 (cborData, byteIdx);
371411 // slither-disable-end unused-return
372412
373413 allocations[i].provider = CommonTypes.FilActorId.wrap (provider);
374414 allocations[i].size = size;
415+ allocations[i].allocationTime = int128 (termMax + expiration);
416+
417+ if (allocations[i].allocationTime > longestAllocation.allocationTime) {
418+ longestAllocation = allocations[i];
419+ }
375420 }
376421
377422 (claimExtensionRequestsLength, byteIdx) = CBORDecoder.readFixedArray (cborData, byteIdx);
0 commit comments