-
Notifications
You must be signed in to change notification settings - Fork 0
[Fil 1232] updated validations for transfer method in Client SC #44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
112f6fe
67df9e1
b77b3ed
a4ca39f
dcea245
3f8dd9c
c0d2f77
677e78f
1b780d2
71d8ecc
22bd963
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,7 @@ import {UtilsHandlers} from "filecoin-solidity/v0.8/utils/UtilsHandlers.sol"; | |
| import {MinerUtils} from "./libs/MinerUtils.sol"; | ||
| import {BeneficiaryFactory} from "./BeneficiaryFactory.sol"; | ||
| import {AllocationResponseCbor} from "./libs/AllocationResponseCbor.sol"; | ||
| import {MinerTypes} from "filecoin-solidity/v0.8/types/MinerTypes.sol"; | ||
|
|
||
| /** | ||
| * @title Client | ||
|
|
@@ -162,9 +163,17 @@ contract Client is Initializable, AccessControlUpgradeable, UUPSUpgradeable { | |
| */ | ||
| error AllocationNotFound(CommonTypes.FilActorId provider, address client, uint64 allocationId); | ||
|
|
||
| /** | ||
| * @notice Thrown if beneficiary allocation expiration is insufficient | ||
| */ | ||
| error InsufficientBeneficiaryAllocationExpiration( | ||
| CommonTypes.FilActorId provider, int64 beneficiaryExpiration, int64 requiredExpiration | ||
| ); | ||
|
|
||
| struct ProviderAllocation { | ||
| CommonTypes.FilActorId provider; | ||
| uint64 size; | ||
| int64 allocationTime; | ||
| } | ||
|
|
||
| struct ProviderClaim { | ||
|
|
@@ -259,9 +268,13 @@ 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 | ||
| ) = _deserializeVerifregOperatorData(params.operator_data); | ||
|
|
||
| _verifyBeneficiaryExpiration(longestAllocation); | ||
| _verifyAndRegisterAllocations(allocations); | ||
| _verifyAndRegisterClaimExtensions(claimExtensions); | ||
| emit DatacapSpent(msg.sender, datacapAmount); | ||
|
|
@@ -364,70 +377,109 @@ contract Client is Initializable, AccessControlUpgradeable, UUPSUpgradeable { | |
| } | ||
| } | ||
|
|
||
| /** | ||
| * @notice Verifies that the beneficiary expiration is sufficient for the longest allocation. | ||
| * @param longestAllocation The longest allocation. | ||
| * @dev Reverts with InsufficientBeneficiaryExpiration if the beneficiary expiration is insufficient. | ||
| */ | ||
| function _verifyBeneficiaryExpiration(ProviderAllocation memory longestAllocation) internal view { | ||
| if (longestAllocation.allocationTime != 0) { | ||
| MinerTypes.GetBeneficiaryReturn memory beneficiary = | ||
| MinerUtils.getBeneficiaryWithChecks(longestAllocation.provider, beneficiaryFactory, true, true, true); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can surely move it here, but why should I check everyone when in the task it is written to check only Miner’s beneficiary related to this longest allocation? |
||
| int64 beneficiaryExpiration = CommonTypes.ChainEpoch.unwrap(beneficiary.active.term.expiration); | ||
|
|
||
| if (longestAllocation.allocationTime > beneficiaryExpiration + 180 days) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The beneficiary must expire no earlier than 180 days after the allocation ends. |
||
| revert InsufficientBeneficiaryAllocationExpiration( | ||
| longestAllocation.provider, beneficiaryExpiration, longestAllocation.allocationTime | ||
| ); | ||
| } | ||
|
|
||
| return; | ||
| } | ||
| } | ||
|
|
||
| // 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. | ||
| */ | ||
| function _deserializeVerifregOperatorData(bytes memory cborData) | ||
| internal | ||
| pure | ||
| returns (ProviderAllocation[] memory allocations, ProviderClaim[] memory claimExtensions) | ||
| returns ( | ||
| ProviderAllocation[] memory allocations, | ||
| ProviderClaim[] memory claimExtensions, | ||
| ProviderAllocation memory longestAllocation | ||
| ) | ||
| { | ||
| uint256 operatorDataLength; | ||
| uint256 allocationRequestsLength; | ||
| uint256 claimExtensionRequestsLength; | ||
| uint256 resultLength; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why did you change the names of these variables? The previous ones were more readable. Was this due to Solhint or the compiler?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minimizing number of local variables to fit in the 15 slot stack depth limit of EVM. |
||
| uint64 provider; | ||
| uint64 claimId; | ||
| uint64 size; | ||
| 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; | ||
| int64 termMax; | ||
| int64 expiration; | ||
| (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); | ||
| allocations[i].provider = CommonTypes.FilActorId.wrap(provider); | ||
| } | ||
| // slither-disable-start unused-return | ||
| (, byteIdx) = CBORDecoder.readBytes(cborData, byteIdx); // data (CID) | ||
| { | ||
| (size, byteIdx) = CBORDecoder.readUInt64(cborData, byteIdx); | ||
| allocations[i].size = size; | ||
| } | ||
| (, 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].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; | ||
| } | ||
| { | ||
| 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(); | ||
| } | ||
|
|
||
| (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); | ||
| (provider, byteIdx) = CBORDecoder.readUInt64(cborData, byteIdx); | ||
| (claimId, byteIdx) = CBORDecoder.readUInt64(cborData, byteIdx); | ||
| // slither-disable-start unused-return | ||
| (, byteIdx) = CBORDecoder.readInt64(cborData, byteIdx); | ||
| // slither-disable-end unused-return | ||
|
|
||
| if (claimExtensionRequestLength != 3) { | ||
| revert InvalidClaimExtensionRequest(); | ||
| claimExtensions[i].provider = CommonTypes.FilActorId.wrap(provider); | ||
| claimExtensions[i].claim = CommonTypes.FilActorId.wrap(claimId); | ||
| } | ||
|
|
||
| (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); | ||
| } | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need to store
allocationTimefor every allocation? I think this might be unnecessarily gas-consuming. Maybe we could move it to a separate struct or use a different approach.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved it to a new struct