Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions abis/Client.json
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,48 @@
"name": "InsufficientAllowance",
"inputs": []
},
{
"type": "error",
"name": "InsufficientBeneficiaryAllocationExpiration",
"inputs": [
{
"name": "provider",
"type": "uint64",
"internalType": "CommonTypes.FilActorId"
},
{
"name": "beneficiaryExpiration",
"type": "int64",
"internalType": "int64"
},
{
"name": "requiredExpiration",
"type": "int64",
"internalType": "int64"
}
]
},
{
"type": "error",
"name": "InsufficientBeneficiaryClaimExtensionExpiration",
"inputs": [
{
"name": "provider",
"type": "uint64",
"internalType": "CommonTypes.FilActorId"
},
{
"name": "claimExpiration",
"type": "int64",
"internalType": "int64"
},
{
"name": "requiredExpiration",
"type": "int64",
"internalType": "int64"
}
]
},
{
"type": "error",
"name": "InvalidActorID",
Expand Down Expand Up @@ -845,6 +887,11 @@
"name": "NegativeValueNotAllowed",
"inputs": []
},
{
"type": "error",
"name": "NoAllocationOrClaim",
"inputs": []
},
{
"type": "error",
"name": "NoBeneficiarySet",
Expand Down
181 changes: 136 additions & 45 deletions src/Client.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {VerifRegAPI} from "filecoin-solidity/v0.8/VerifRegAPI.sol";
import {UtilsHandlers} from "filecoin-solidity/v0.8/utils/UtilsHandlers.sol";
import {MinerUtils} from "./libs/MinerUtils.sol";
import {BeneficiaryFactory} from "./BeneficiaryFactory.sol";
import {MinerTypes} from "filecoin-solidity/v0.8/types/MinerTypes.sol";

/**
* @title Client
Expand Down Expand Up @@ -140,14 +141,35 @@ contract Client is Initializable, AccessControlUpgradeable, UUPSUpgradeable {
*/
error InvalidBeneficiary(address beneficiary, address expectedBeneficiary);

/**
* @notice Thrown if beneficiary allocation expiration is insufficient
*/
error InsufficientBeneficiaryAllocationExpiration(
CommonTypes.FilActorId provider, int64 beneficiaryExpiration, int64 requiredExpiration
);

/**
* @notice Thrown if beneficiary claim extension expiration is insufficient
*/
error InsufficientBeneficiaryClaimExtensionExpiration(
CommonTypes.FilActorId provider, int64 claimExpiration, int64 requiredExpiration
);

/**
* @notice Thrown if no allocation or claim is found
*/
error NoAllocationOrClaim();

struct ProviderAllocation {
CommonTypes.FilActorId provider;
uint64 size;
int64 allocationTime;
}

struct ProviderClaim {
CommonTypes.FilActorId provider;
CommonTypes.FilActorId claim;
int64 termMax;
}

struct ClientDataUsage {
Expand Down Expand Up @@ -231,9 +253,14 @@ contract Client is Initializable, AccessControlUpgradeable, UUPSUpgradeable {
if (failed) revert InvalidAmount();
uint256 datacapAmount = tokenAmount / TOKEN_PRECISION;

(ProviderAllocation[] memory allocations, ProviderClaim[] memory claimExtensions) =
_deserializeVerifregOperatorData(params.operator_data);
(
ProviderAllocation[] memory allocations,
ProviderClaim[] memory claimExtensions,
ProviderAllocation memory longestAllocation,
ProviderClaim memory longestClaimExtension
) = _deserializeVerifregOperatorData(params.operator_data);

_verifyBeneficiaryExpiration(longestAllocation, longestClaimExtension);
_verifyAndRegisterAllocations(allocations);
_verifyAndRegisterClaimExtensions(claimExtensions);
emit DatacapSpent(msg.sender, datacapAmount);
Expand Down Expand Up @@ -328,70 +355,134 @@ contract Client is Initializable, AccessControlUpgradeable, UUPSUpgradeable {
}
}

/**
* @notice Verifies that the beneficiary expiration is sufficient for the longest allocation.
* @param longestAllocation The longest allocation.
* @param longestClaimExtension The longest claim extension.
* @dev Reverts with InsufficientBeneficiaryExpiration if the beneficiary expiration is insufficient.
*/
function _verifyBeneficiaryExpiration(
ProviderAllocation memory longestAllocation,
ProviderClaim memory longestClaimExtension
) internal {
MinerTypes.GetBeneficiaryReturn memory beneficiary;
int64 beneficiaryExpiration;

if (longestClaimExtension.termMax != 0) {
beneficiary = MinerUtils.getBeneficiaryWithChecks(
longestClaimExtension.provider, beneficiaryFactory, true, true, true
);
int64 beneficiaryExpiration = CommonTypes.ChainEpoch.unwrap(beneficiary.active.term.expiration);

if (longestClaimExtension.termMax > beneficiaryExpiration + 250 weeks) {
revert InsufficientBeneficiaryClaimExtensionExpiration(
longestClaimExtension.provider, beneficiaryExpiration, longestClaimExtension.termMax
);
}
return;
}

if (longestAllocation.allocationTime != 0) {
beneficiary =
MinerUtils.getBeneficiaryWithChecks(longestAllocation.provider, beneficiaryFactory, true, true, true);
beneficiaryExpiration = CommonTypes.ChainEpoch.unwrap(beneficiary.active.term.expiration);

if (longestAllocation.allocationTime > beneficiaryExpiration + 180 days) {
revert InsufficientBeneficiaryAllocationExpiration(
longestAllocation.provider, beneficiaryExpiration, longestAllocation.allocationTime
);
}

return;
}

revert NoAllocationOrClaim();
}

// solhint-disable function-max-lines
/**
* @notice Deserialize Verifreg Operator Data.
* @param cborData The cbor encoded operator data.
* @return allocations Array of provider allocations.
* @return claimExtensions Array of provider claims.
* @return longestAllocation Allocation with the longest term.
* @return longestClaimExtension Claim extension with the longest term.
*/
function _deserializeVerifregOperatorData(bytes memory cborData)
internal
pure
returns (ProviderAllocation[] memory allocations, ProviderClaim[] memory claimExtensions)
returns (
ProviderAllocation[] memory allocations,
ProviderClaim[] memory claimExtensions,
ProviderAllocation memory longestAllocation,
ProviderClaim memory longestClaimExtension
)
{
uint256 operatorDataLength;
uint256 allocationRequestsLength;
uint256 claimExtensionRequestsLength;
uint256 resultLength;
uint64 provider;
uint64 claimId;
uint64 size;
int64 termMax;
int64 expiration;
uint256 byteIdx = 0;

(operatorDataLength, byteIdx) = CBORDecoder.readFixedArray(cborData, byteIdx);
if (operatorDataLength != 2) revert InvalidOperatorData();

(allocationRequestsLength, byteIdx) = CBORDecoder.readFixedArray(cborData, byteIdx);
allocations = new ProviderAllocation[](allocationRequestsLength);
for (uint256 i = 0; i < allocationRequestsLength; i++) {
uint256 allocationRequestLength;
(allocationRequestLength, byteIdx) = CBORDecoder.readFixedArray(cborData, byteIdx);
{
(resultLength, byteIdx) = CBORDecoder.readFixedArray(cborData, byteIdx);
if (resultLength != 2) revert InvalidOperatorData();
}
{
uint64 size;
(resultLength, byteIdx) = CBORDecoder.readFixedArray(cborData, byteIdx);
allocations = new ProviderAllocation[](resultLength);
for (uint256 i = 0; i < resultLength; i++) {
uint256 allocationRequestLength;
(allocationRequestLength, byteIdx) = CBORDecoder.readFixedArray(cborData, byteIdx);

if (allocationRequestLength != 6) {
revert InvalidAllocationRequest();
}

if (allocationRequestLength != 6) {
revert InvalidAllocationRequest();
(provider, byteIdx) = CBORDecoder.readUInt64(cborData, byteIdx);
// slither-disable-start unused-return
(, byteIdx) = CBORDecoder.readBytes(cborData, byteIdx); // data (CID)
(size, byteIdx) = CBORDecoder.readUInt64(cborData, byteIdx);
(, byteIdx) = CBORDecoder.readInt64(cborData, byteIdx); // termMin
// slither-disable-end unused-return
(termMax, byteIdx) = CBORDecoder.readInt64(cborData, byteIdx);
(expiration, byteIdx) = CBORDecoder.readInt64(cborData, byteIdx);

allocations[i].provider = CommonTypes.FilActorId.wrap(provider);
allocations[i].size = size;
allocations[i].allocationTime = termMax + expiration;

if (allocations[i].allocationTime > longestAllocation.allocationTime) {
longestAllocation = allocations[i];
}
}

(provider, byteIdx) = CBORDecoder.readUInt64(cborData, byteIdx);
// slither-disable-start unused-return
(, byteIdx) = CBORDecoder.readBytes(cborData, byteIdx); // data (CID)
(size, byteIdx) = CBORDecoder.readUInt64(cborData, byteIdx);
(, byteIdx) = CBORDecoder.readInt64(cborData, byteIdx); // termMin
(, byteIdx) = CBORDecoder.readInt64(cborData, byteIdx); // termMax
(, byteIdx) = CBORDecoder.readInt64(cborData, byteIdx); // expiration
// slither-disable-end unused-return

allocations[i].provider = CommonTypes.FilActorId.wrap(provider);
allocations[i].size = size;
}

(claimExtensionRequestsLength, byteIdx) = CBORDecoder.readFixedArray(cborData, byteIdx);
claimExtensions = new ProviderClaim[](claimExtensionRequestsLength);
for (uint256 i = 0; i < claimExtensionRequestsLength; i++) {
uint256 claimExtensionRequestLength;
(claimExtensionRequestLength, byteIdx) = CBORDecoder.readFixedArray(cborData, byteIdx);
{
uint64 claimId;
(resultLength, byteIdx) = CBORDecoder.readFixedArray(cborData, byteIdx);
claimExtensions = new ProviderClaim[](resultLength);
for (uint256 i = 0; i < resultLength; i++) {
uint256 claimExtensionRequestLength;
(claimExtensionRequestLength, byteIdx) = CBORDecoder.readFixedArray(cborData, byteIdx);

if (claimExtensionRequestLength != 3) {
revert InvalidClaimExtensionRequest();
}
if (claimExtensionRequestLength != 3) {
revert InvalidClaimExtensionRequest();
}

(provider, byteIdx) = CBORDecoder.readUInt64(cborData, byteIdx);
(claimId, byteIdx) = CBORDecoder.readUInt64(cborData, byteIdx);
(termMax, byteIdx) = CBORDecoder.readInt64(cborData, byteIdx);

(provider, byteIdx) = CBORDecoder.readUInt64(cborData, byteIdx);
(claimId, byteIdx) = CBORDecoder.readUInt64(cborData, byteIdx);
// slither-disable-start unused-return
(, byteIdx) = CBORDecoder.readInt64(cborData, byteIdx); // termMax
// slither-disable-end unused-return
claimExtensions[i].provider = CommonTypes.FilActorId.wrap(provider);
claimExtensions[i].claim = CommonTypes.FilActorId.wrap(claimId);
claimExtensions[i].termMax = termMax;

claimExtensions[i].provider = CommonTypes.FilActorId.wrap(provider);
claimExtensions[i].claim = CommonTypes.FilActorId.wrap(claimId);
if (termMax > longestClaimExtension.termMax) {
longestClaimExtension = claimExtensions[i];
}
}
}
}

Expand Down
Loading