From ed6d77dfdf794e028081e19cda89a014bdb9f69b Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Tue, 30 May 2023 17:21:21 +0100 Subject: [PATCH 01/99] First draft on TalentLayerServiceV2.sol Signed-off-by: Quentin D.C --- contracts/Upgrades/TalentLayerServiceV2.sol | 698 ++++++++++++++++++++ 1 file changed, 698 insertions(+) create mode 100644 contracts/Upgrades/TalentLayerServiceV2.sol diff --git a/contracts/Upgrades/TalentLayerServiceV2.sol b/contracts/Upgrades/TalentLayerServiceV2.sol new file mode 100644 index 00000000..33f3c148 --- /dev/null +++ b/contracts/Upgrades/TalentLayerServiceV2.sol @@ -0,0 +1,698 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import {ITalentLayerID} from "../interfaces/ITalentLayerID.sol"; +import {ITalentLayerPlatformID} from "../interfaces/ITalentLayerPlatformID.sol"; +import {ERC2771RecipientUpgradeable} from "../libs/ERC2771RecipientUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import {ECDSAUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol"; + +/** + * @title TalentLayerService Contract + * @author TalentLayer Team | Website: https://talentlayer.org | Twitter: @talentlayer + */ +contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUPSUpgradeable, AccessControlUpgradeable { + // =========================== Enum ============================== + + /** + * @notice Enum service status + */ + enum Status { + Opened, + Confirmed, + Finished, + Cancelled, + Uncompleted + } + + /** + * @notice Enum proposal status + */ + enum ProposalStatus { + Pending, + Validated + } + + // =========================== Struct ============================== + + /** + * @notice Service information struct + * @param status the current status of a service + * @param ownerId the talentLayerId of the buyer + * @param acceptedProposalId the accepted proposal ID, which is the ID of the user who submitted the proposal + * @param dataUri token Id to IPFS URI mapping + * @param transactionId the escrow transaction ID linked to the service + * @param platformId the platform ID on which the service was created + * @param token the token used for the service's payments, including the referral amount + * @param referralAmount the amount which the referrer will receive if a proposal is validated by un user which was referred + */ + struct Service { + Status status; + uint256 ownerId; + uint256 acceptedProposalId; + string dataUri; + uint256 transactionId; + uint256 platformId; + address token; + uint256 referralAmount; + } + + /** + * @notice Proposal information struct + * @param status the current status of a service + * @param ownerId the talentLayerId of the seller + * @param rateToken the token choose for the payment + * @param rateAmount the amount of token chosen + * @param dataUri token Id to IPFS URI mapping + * @param expirationDate the timeout for the proposal + */ + struct Proposal { + ProposalStatus status; + uint256 ownerId; + address rateToken; + uint256 rateAmount; + uint256 platformId; + string dataUri; + uint256 expirationDate; + } + + /** + * @notice Whitelisted token information struct + * @param tokenAddress the token address + * @param minimumTransactionAmount the minimum transaction value + */ + struct AllowedToken { + bool isWhitelisted; + uint256 minimumTransactionAmount; + } + + // =========================== Events ============================== + + /** + * @notice Emitted after a new service is created + * @param id The service ID (incremental) + * @param ownerId the talentLayerId of the buyer + * @param platformId platform ID on which the Service token was minted + * @param dataUri token Id to IPFS URI mapping + */ + event ServiceCreated(uint256 id, uint256 ownerId, uint256 platformId, string dataUri); + + /** + * @notice Emitted after a new service is created with referral data + * @param id The service ID (incremental) + * @param ownerId the talentLayerId of the buyer + * @param platformId platform ID on which the Service token was minted + * @param dataUri token Id to IPFS URI mapping + * @param token the token used for the service's payments, including the referral amount + * @param referralAmount the amount which the referrer will receive if a proposal is validated by un user which was referred + */ + event ServiceCreatedWithReferral( + uint256 id, + uint256 ownerId, + uint256 platformId, + string dataUri, + address token, + uint256 referralAmount + ); + + /** + * @notice Emitted after a service is cancelled by the owner + * @param id The service ID + */ + event ServiceCancelled(uint256 id); + + /** + * @notice Emit when Cid is updated for a Service + * @param id The service ID + * @param dataUri New service Data URI + */ + event ServiceDetailedUpdated(uint256 indexed id, string dataUri); + + /** + * @notice Emitted after a new proposal is created + * @param serviceId The service id + * @param ownerId The talentLayerId of the seller who made the proposal + * @param dataUri token Id to IPFS URI mapping + * @param status proposal status + * @param rateToken the token choose for the payment + * @param rateAmount the amount of token chosen + * @param platformId the platform ID on which the proposal was created + * @param expirationDate the timeout for the proposal + */ + event ProposalCreated( + uint256 serviceId, + uint256 ownerId, + string dataUri, + ProposalStatus status, + address rateToken, + uint256 rateAmount, + uint256 platformId, + uint256 expirationDate + ); + + /** + * @notice Emitted after an existing proposal has been updated + * @param serviceId The service id + * @param ownerId The talentLayerId of the seller who made the proposal + * @param dataUri token Id to IPFS URI mapping + * @param rateToken the token choose for the payment + * @param rateAmount the amount of token chosen + * @param expirationDate the timeout for the proposal + */ + event ProposalUpdated( + uint256 serviceId, + uint256 ownerId, + string dataUri, + address rateToken, + uint256 rateAmount, + uint256 expirationDate + ); + + /** + * @notice Emitted when the contract owner adds or removes a token from the allowed payment tokens list + * @param tokenAddress The address of the payment token + * @param isWhitelisted Whether the token is allowed or not + * @param minimumTransactionAmount The minimum transaction fees for the token + */ + event AllowedTokenListUpdated(address tokenAddress, bool isWhitelisted, uint256 minimumTransactionAmount); + + /** + * @notice Emitted when the contract owner updates the minimum completion percentage for services + * @param minCompletionPercentage The new minimum completion percentage + */ + event MinCompletionPercentageUpdated(uint256 minCompletionPercentage); + + // =========================== Mappings & Variables ============================== + + /** + * @notice incremental service Id + */ + uint256 public nextServiceId; + + /** + * @notice TalentLayerId address + */ + ITalentLayerID private tlId; + + /** + * @notice TalentLayer Platform ID registry contract + */ + ITalentLayerPlatformID public talentLayerPlatformIdContract; + + /** + * @notice services mappings index by ID + */ + mapping(uint256 => Service) public services; + + /** + * @notice proposals mappings index by service ID and owner TID + */ + mapping(uint256 => mapping(uint256 => Proposal)) public proposals; + + /** + * @notice TLUserId mappings to number of services created used as a nonce in createService signature + */ + mapping(uint256 => uint256) public serviceNonce; + + /** + * @notice TLUserId mappings to number of proposals created + */ + mapping(uint256 => uint256) public proposalNonce; + + /** + * @notice Allowed payment tokens addresses + */ + mapping(address => AllowedToken) public allowedTokenList; + + /** + * @notice Minimum percentage of the proposal amount to be released for considering the service as completed + */ + uint256 public minCompletionPercentage; + + /** + * @notice Role granting Escrow permission + */ + bytes32 public constant ESCROW_ROLE = keccak256("ESCROW_ROLE"); + + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + _disableInitializers(); + } + + // =========================== Modifiers ============================== + + /** + * @notice Check if the given address is either the owner of the delegate of the given user + * @param _profileId The TalentLayer ID of the user + */ + modifier onlyOwnerOrDelegate(uint256 _profileId) { + require(tlId.isOwnerOrDelegate(_profileId, _msgSender()), "Not owner or delegate"); + _; + } + + // =========================== Initializers ============================== + + /** + * @notice First initializer function + * @param _talentLayerIdAddress TalentLayerId contract address + * @param _talentLayerPlatformIdAddress TalentLayerPlatformId contract address + */ + function initialize(address _talentLayerIdAddress, address _talentLayerPlatformIdAddress) public initializer { + __Ownable_init(); + __AccessControl_init(); + __UUPSUpgradeable_init(); + _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); + tlId = ITalentLayerID(_talentLayerIdAddress); + talentLayerPlatformIdContract = ITalentLayerPlatformID(_talentLayerPlatformIdAddress); + nextServiceId = 1; + updateMinCompletionPercentage(30); + } + + // =========================== View functions ============================== + + /** + * @notice Returns the whole service data information + * @param _serviceId Service identifier + */ + function getService(uint256 _serviceId) external view returns (Service memory) { + require(_serviceId < nextServiceId, "This service doesn't exist"); + return services[_serviceId]; + } + + /** + * @notice Returns the specific proposal for the attached service + * @param _serviceId Service identifier + * @param _proposalId Proposal identifier + */ + function getProposal(uint256 _serviceId, uint256 _proposalId) external view returns (Proposal memory) { + return proposals[_serviceId][_proposalId]; + } + + /** + * @notice Returns the specific service and the proposal linked to it + * @param _serviceId Service identifier + * @param _proposalId Proposal identifier + */ + function getServiceAndProposal( + uint256 _serviceId, + uint256 _proposalId + ) external view returns (Service memory, Proposal memory) { + Service memory service = services[_serviceId]; + Proposal memory proposal = proposals[_serviceId][_proposalId]; + return (service, proposal); + } + + /** + * @notice Indicates whether the token in parameter is allowed for payment + * @param _tokenAddress Token address + */ + function isTokenAllowed(address _tokenAddress) external view returns (bool) { + return allowedTokenList[_tokenAddress].isWhitelisted; + } + + // =========================== User functions ============================== + + /** + * @notice Allows a buyer to initiate an open service + * @param _profileId The TalentLayer ID of the user owner of the service + * @param _platformId platform ID on which the Service token was created + * @param _dataUri IPFS URI of the offchain data of the service + * @param _signature optional platform signature to allow the operation + */ + function createService( + uint256 _profileId, + uint256 _platformId, + string calldata _dataUri, + bytes calldata _signature + ) public payable onlyOwnerOrDelegate(_profileId) returns (uint256) { + _validateService(_profileId, _platformId, _dataUri, _signature); + + uint256 id = nextServiceId; + nextServiceId++; + + Service storage service = services[id]; + service.status = Status.Opened; + service.ownerId = _profileId; + service.dataUri = _dataUri; + service.platformId = _platformId; + + if (serviceNonce[_profileId] == 0 && proposalNonce[_profileId] == 0) { + tlId.setHasActivity(_profileId); + } + serviceNonce[_profileId]++; + + emit ServiceCreated(id, _profileId, _platformId, _dataUri); + + return id; + } + + /** + * @notice Allows a buyer to initiate an open service + * @param _profileId The TalentLayer ID of the user owner of the service + * @param _platformId platform ID on which the Service token was created + * @param _dataUri IPFS URI of the offchain data of the service + * @param _signature optional platform signature to allow the operation + * @param _token the token used for the referral amount + * @param _referralAmount the amount which the referrer will receive if a proposal is validated by un user which was referred + */ + function createServiceWithReferral( + uint256 _profileId, + uint256 _platformId, + string calldata _dataUri, + bytes calldata _signature, + address _token, + uint256 _referralAmount + ) public payable onlyOwnerOrDelegate(_profileId) returns (uint256) { + _validateService(_profileId, _platformId, _dataUri, _signature); + + uint256 id = nextServiceId; + nextServiceId++; + + Service storage service = services[id]; + service.status = Status.Opened; + service.ownerId = _profileId; + service.dataUri = _dataUri; + service.platformId = _platformId; + service.token = _token; + service.referralAmount = _referralAmount; + + if (serviceNonce[_profileId] == 0 && proposalNonce[_profileId] == 0) { + tlId.setHasActivity(_profileId); + } + serviceNonce[_profileId]++; + + emit ServiceCreatedWithReferral(id, _profileId, _platformId, _dataUri, _token, _referralAmount); + + return id; + } + + /** + * @notice Allows an seller to propose his service for a service + * @param _profileId The TalentLayer ID of the user owner of the proposal + * @param _serviceId The service linked to the new proposal + * @param _rateToken the token choose for the payment + * @param _rateAmount the amount of token chosen + * @param _dataUri token Id to IPFS URI mapping + * @param _platformId platform ID from where the proposal is created + * @param _expirationDate the time before the proposal is automatically validated + * @param _signature optional platform signature to allow the operation + */ + function createProposal( + uint256 _profileId, + uint256 _serviceId, + address _rateToken, + uint256 _rateAmount, + uint256 _platformId, + string calldata _dataUri, + uint256 _expirationDate, + bytes calldata _signature + ) public payable onlyOwnerOrDelegate(_profileId) { + _validateProposal(_profileId, _serviceId, _rateToken, _rateAmount, _platformId, _dataUri, _signature); + + proposals[_serviceId][_profileId] = Proposal({ + status: ProposalStatus.Pending, + ownerId: _profileId, + rateToken: _rateToken, + rateAmount: _rateAmount, + platformId: _platformId, + dataUri: _dataUri, + expirationDate: _expirationDate + }); + + if (serviceNonce[_profileId] == 0 && proposalNonce[_profileId] == 0) { + tlId.setHasActivity(_profileId); + } + proposalNonce[_profileId]++; + + emit ProposalCreated( + _serviceId, + _profileId, + _dataUri, + ProposalStatus.Pending, + _rateToken, + _rateAmount, + _platformId, + _expirationDate + ); + } + + /** + * @notice Allows the owner to update his own proposal for a given service + * @param _profileId The TalentLayer ID of the user + * @param _serviceId The service linked to the new proposal + * @param _rateToken the token choose for the payment + * @param _rateAmount the amount of token chosen + * @param _dataUri token Id to IPFS URI mapping + * @param _expirationDate the time before the proposal is automatically validated + */ + function updateProposal( + uint256 _profileId, + uint256 _serviceId, + address _rateToken, + uint256 _rateAmount, + string calldata _dataUri, + uint256 _expirationDate + ) public onlyOwnerOrDelegate(_profileId) { + require(allowedTokenList[_rateToken].isWhitelisted, "Token not allowed"); + + Service storage service = services[_serviceId]; + Proposal storage proposal = proposals[_serviceId][_profileId]; + require(service.status == Status.Opened, "Service not opened"); + require(proposal.ownerId == _profileId, "Not the owner"); + require(bytes(_dataUri).length == 46, "Invalid cid"); + require(proposal.status != ProposalStatus.Validated, "Already validated"); + require(_rateAmount >= allowedTokenList[_rateToken].minimumTransactionAmount, "Amount too low"); + + proposal.rateToken = _rateToken; + proposal.rateAmount = _rateAmount; + proposal.dataUri = _dataUri; + proposal.expirationDate = _expirationDate; + + emit ProposalUpdated(_serviceId, _profileId, _dataUri, _rateToken, _rateAmount, _expirationDate); + } + + /** + * @notice Allow the escrow contract to upgrade the Service state after a deposit has been done + * @param _serviceId Service identifier + * @param _proposalId The chosen proposal id for this service + * @param _transactionId The escrow transaction Id + */ + function afterDeposit( + uint256 _serviceId, + uint256 _proposalId, + uint256 _transactionId + ) external onlyRole(ESCROW_ROLE) { + Service storage service = services[_serviceId]; + Proposal storage proposal = proposals[_serviceId][_proposalId]; + + service.status = Status.Confirmed; + service.acceptedProposalId = proposal.ownerId; + service.transactionId = _transactionId; + proposal.status = ProposalStatus.Validated; + } + + /** + * @notice Allows the contract owner to add or remove a token from the allowed payment tokens list + * @param _tokenAddress The address of the payment token + * @param _isWhitelisted Whether the token is allowed or not + * @param _minimumTransactionAmount the minimum amount of token allowed for a transaction + * @dev Only the contract owner can call this function. The owner can't never remove the Ox address + */ + function updateAllowedTokenList( + address _tokenAddress, + bool _isWhitelisted, + uint256 _minimumTransactionAmount + ) public onlyOwner { + if (_tokenAddress == address(0) && !_isWhitelisted) { + revert("Owner can't remove Ox address"); + } + allowedTokenList[_tokenAddress].isWhitelisted = _isWhitelisted; + allowedTokenList[_tokenAddress].minimumTransactionAmount = _minimumTransactionAmount; + + emit AllowedTokenListUpdated(_tokenAddress, _isWhitelisted, _minimumTransactionAmount); + } + + /** + * @notice Allow the escrow contract to upgrade the Service state after the full payment has been received by the seller + * @param _serviceId Service identifier + * @param _releasedAmount The total amount of the payment released to the seller + */ + function afterFullPayment(uint256 _serviceId, uint256 _releasedAmount) external onlyRole(ESCROW_ROLE) { + Service storage service = services[_serviceId]; + Proposal storage proposal = proposals[_serviceId][service.acceptedProposalId]; + + uint256 releasedPercentage = (_releasedAmount * 100) / proposal.rateAmount; + if (releasedPercentage >= minCompletionPercentage) { + service.status = Status.Finished; + } else { + service.status = Status.Uncompleted; + } + } + + /** + * @notice Update Service URI data + * @param _profileId The TalentLayer ID of the user, owner of the service + * @param _serviceId, Service ID to update + * @param _dataUri New IPFS URI + */ + function updateServiceData( + uint256 _profileId, + uint256 _serviceId, + string calldata _dataUri + ) public onlyOwnerOrDelegate(_profileId) { + Service storage service = services[_serviceId]; + require(service.ownerId == _profileId, "Not the owner"); + require(service.status == Status.Opened, "status must be opened"); + require(bytes(_dataUri).length == 46, "Invalid cid"); + + service.dataUri = _dataUri; + + emit ServiceDetailedUpdated(_serviceId, _dataUri); + } + + /** + * @notice Cancel an open Service + * @param _profileId The TalentLayer ID of the user, owner of the service + * @param _serviceId Service ID to cancel + */ + function cancelService(uint256 _profileId, uint256 _serviceId) public onlyOwnerOrDelegate(_profileId) { + Service storage service = services[_serviceId]; + + require(service.ownerId == _profileId, "not the owner"); + require(service.status == Status.Opened, "status must be opened"); + service.status = Status.Cancelled; + + emit ServiceCancelled(_serviceId); + } + + // =========================== Owner functions ============================== + + /** + * @notice Allows the contract owner to update the minimum completion percentage for services + * @param _minCompletionPercentage The new completion percentage + * @dev Only the contract owner can call this function + */ + function updateMinCompletionPercentage(uint256 _minCompletionPercentage) public onlyRole(DEFAULT_ADMIN_ROLE) { + minCompletionPercentage = _minCompletionPercentage; + + emit MinCompletionPercentageUpdated(_minCompletionPercentage); + } + + // =========================== Overrides ============================== + + function _msgSender() + internal + view + virtual + override(ContextUpgradeable, ERC2771RecipientUpgradeable) + returns (address) + { + return ERC2771RecipientUpgradeable._msgSender(); + } + + function _msgData() + internal + view + virtual + override(ContextUpgradeable, ERC2771RecipientUpgradeable) + returns (bytes calldata) + { + return ERC2771RecipientUpgradeable._msgData(); + } + + // =========================== Private functions ============================== + + /** + * @notice Validate a new service + * @param _profileId The TalentLayer ID of the user + * @param _platformId platform ID on which the Service was created + * @param _dataUri token Id to IPFS URI mapping + * @param _signature platform signature to allow the operation + */ + function _validateService( + uint256 _profileId, + uint256 _platformId, + string calldata _dataUri, + bytes calldata _signature + ) private view { + uint256 servicePostingFee = talentLayerPlatformIdContract.getServicePostingFee(_platformId); + require(msg.value == servicePostingFee, "Non-matching funds"); + require(bytes(_dataUri).length == 46, "Invalid cid"); + + address platformSigner = talentLayerPlatformIdContract.getSigner(_platformId); + if (platformSigner != address(0)) { + bytes32 messageHash = keccak256( + abi.encodePacked("createService", _profileId, ";", serviceNonce[_profileId], _dataUri) + ); + _validatePlatformSignature(_signature, messageHash, platformSigner); + } + } + + /** + * @notice Validate a new proposal + * @param _profileId The TalentLayer ID of the user + * @param _serviceId The service linked to the new proposal + * @param _rateToken the token choose for the payment + * @param _rateAmount the amount of token chosen + * @param _platformId platform ID on which the Proposal was created + * @param _dataUri token Id to IPFS URI mapping + * @param _signature platform signature to allow the operation + */ + function _validateProposal( + uint256 _profileId, + uint256 _serviceId, + address _rateToken, + uint256 _rateAmount, + uint256 _platformId, + string calldata _dataUri, + bytes calldata _signature + ) private view { + require(allowedTokenList[_rateToken].isWhitelisted, "Token not allowed"); + uint256 proposalPostingFee = talentLayerPlatformIdContract.getProposalPostingFee(_platformId); + require(msg.value == proposalPostingFee, "Non-matching funds"); + require(_rateAmount >= allowedTokenList[_rateToken].minimumTransactionAmount, "Amount too low"); + + Service storage service = services[_serviceId]; + require(service.status == Status.Opened, "Service not opened"); + require(service.ownerId != 0, "Service not exist"); + require(proposals[_serviceId][_profileId].ownerId != _profileId, "proposal already exist"); + // require(service.token == _rateToken, "Non-matching tokens"); + + require(service.ownerId != _profileId, "can't create for your own service"); + require(bytes(_dataUri).length == 46, "Invalid cid"); + + address platformSigner = talentLayerPlatformIdContract.getSigner(_platformId); + if (platformSigner != address(0)) { + bytes32 messageHash = keccak256(abi.encodePacked("createProposal", _profileId, ";", _serviceId, _dataUri)); + _validatePlatformSignature(_signature, messageHash, platformSigner); + } + } + + /** + * @notice Validate the platform ECDSA signature for a given message hash operation + * @param _signature platform signature to allow the operation + * @param _messageHash The hash of a generated message corresponding to the operation + * @param _platformSigner The address defined by the platform as signer + */ + function _validatePlatformSignature( + bytes calldata _signature, + bytes32 _messageHash, + address _platformSigner + ) private pure { + bytes32 ethMessageHash = ECDSAUpgradeable.toEthSignedMessageHash(_messageHash); + address signer = ECDSAUpgradeable.recover(ethMessageHash, _signature); + require(_platformSigner == signer, "invalid signature"); + } + + // =========================== Internal functions ============================== + + /** + * @notice Function that revert when `_msgSender()` is not authorized to upgrade the contract. Called by + * {upgradeTo} and {upgradeToAndCall}. + * @param newImplementation address of the new contract implementation + */ + function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} +} From 8ad8fdadad918017b8397764167548decd208a56 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Tue, 30 May 2023 17:21:29 +0100 Subject: [PATCH 02/99] First draft on TalentLayerEscrowV2.sol Signed-off-by: Quentin D.C --- contracts/Upgrades/TalentLayerEscrowV2.sol | 1045 ++++++++++++++++++++ 1 file changed, 1045 insertions(+) create mode 100644 contracts/Upgrades/TalentLayerEscrowV2.sol diff --git a/contracts/Upgrades/TalentLayerEscrowV2.sol b/contracts/Upgrades/TalentLayerEscrowV2.sol new file mode 100644 index 00000000..b0ce414c --- /dev/null +++ b/contracts/Upgrades/TalentLayerEscrowV2.sol @@ -0,0 +1,1045 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; +import {ITalentLayerService} from "../interfaces/ITalentLayerService.sol"; +import {ITalentLayerID} from "../interfaces/ITalentLayerID.sol"; +import {ITalentLayerPlatformID} from "../interfaces/ITalentLayerPlatformID.sol"; +import "../libs/ERC2771RecipientUpgradeable.sol"; +import {IArbitrable} from "../interfaces/IArbitrable.sol"; +import {Arbitrator} from "../Arbitrator.sol"; + +/** + * @title TalentLayer Escrow Contract + * @author TalentLayer Team | Website: https://talentlayer.org | Twitter: @talentlayer + */ +contract TalentLayerEscrowV2 is + Initializable, + ERC2771RecipientUpgradeable, + PausableUpgradeable, + UUPSUpgradeable, + IArbitrable +{ + using CountersUpgradeable for CountersUpgradeable.Counter; + using SafeERC20Upgradeable for IERC20Upgradeable; + + // =========================== Enum ============================== + + /** + * @notice Enum payment type + */ + enum PaymentType { + Release, + Reimburse + } + + /** + * @notice Arbitration fee payment type enum + */ + enum ArbitrationFeePaymentType { + Pay, + Reimburse + } + + /** + * @notice party type enum + */ + enum Party { + Sender, + Receiver + } + + /** + * @notice Transaction status enum + */ + enum Status { + NoDispute, // no dispute has arisen about the transaction + WaitingSender, // receiver has paid arbitration fee, while sender still has to do it + WaitingReceiver, // sender has paid arbitration fee, while receiver still has to do it + DisputeCreated, // both parties have paid the arbitration fee and a dispute has been created + Resolved // the transaction is solved (either no dispute has ever arisen or the dispute has been resolved) + } + + // =========================== Struct ============================== + + /** + * @notice Transaction struct + * @param id Incremental identifier + * @param sender The party paying the escrow amount + * @param receiver The intended receiver of the escrow amount + * @param token The token used for the transaction + * @param amount The amount of the transaction EXCLUDING FEES + * @param releasedAmount The amount of the transaction that has been released to the receiver EXCLUDING FEES + * @param serviceId The ID of the associated service + * @param proposalId The id of the validated proposal + * @param protocolEscrowFeeRate The %fee (per ten thousands) paid to the protocol's owner + * @param originServiceFeeRate The %fee (per ten thousands) paid to the platform on which the service was created + * @param originValidatedProposalFeeRate the %fee (per ten thousands) paid to the platform on which the proposal was validated + * @param arbitrator The address of the contract that can rule on a dispute for the transaction. + * @param status The status of the transaction for the dispute procedure. + * @param disputeId The ID of the dispute, if it exists + * @param senderFee Total fees paid by the sender for the dispute procedure. + * @param receiverFee Total fees paid by the receiver for the dispute procedure. + * @param lastInteraction Last interaction for the dispute procedure. + * @param arbitratorExtraData Extra data to set up the arbitration. + * @param arbitrationFeeTimeout timeout for parties to pay the arbitration fee + */ + struct Transaction { + uint256 id; + address sender; + address receiver; + address token; + uint256 amount; + uint256 releasedAmount; + uint256 serviceId; + uint256 proposalId; + uint16 protocolEscrowFeeRate; + uint16 originServiceFeeRate; + uint16 originValidatedProposalFeeRate; + Arbitrator arbitrator; + Status status; + uint256 disputeId; + uint256 senderFee; + uint256 receiverFee; + uint256 lastInteraction; + bytes arbitratorExtraData; + uint256 arbitrationFeeTimeout; + } + + // =========================== Events ============================== + + /** + * @notice Emitted after each payment + * @param _transactionId The id of the transaction. + * @param _paymentType Whether the payment is a release or a reimbursement. + * @param _token The address of the token used for the payment. + * @param _amount The amount paid. + * @param _serviceId The id of the concerned service. + */ + event Payment( + uint256 _transactionId, + PaymentType _paymentType, + address _token, + uint256 _amount, + uint256 _serviceId + ); + + /** + * @notice Emitted after the total amount of a transaction has been paid. At this moment the service is considered finished. + * @param _serviceId The service ID + */ + event PaymentCompleted(uint256 _serviceId); + + /** + * @notice Emitted after the protocol fee was updated + * @param _protocolEscrowFeeRate The new protocol fee + */ + event ProtocolEscrowFeeRateUpdated(uint16 _protocolEscrowFeeRate); + + /** + * @notice Emitted after a platform withdraws its balance + * @param _platformId The Platform ID to which the balance is transferred. + * @param _token The address of the token used for the payment. + * @param _amount The amount transferred. + */ + event FeesClaimed(uint256 _platformId, address indexed _token, uint256 _amount); + + /** + * @notice Emitted after an origin service fee is released to a platform's balance + * @param _platformId The platform ID. + * @param _serviceId The related service ID. + * @param _token The address of the token used for the payment. + * @param _amount The amount released. + */ + event OriginServiceFeeRateReleased( + uint256 _platformId, + uint256 _serviceId, + address indexed _token, + uint256 _amount + ); + + /** + * @notice Emitted after an origin service fee is released to a platform's balance + * @param _platformId The platform ID. + * @param _serviceId The related service ID. + * @param _token The address of the token used for the payment. + * @param _amount The amount released. + */ + event OriginValidatedProposalFeeRateReleased( + uint256 _platformId, + uint256 _serviceId, + address indexed _token, + uint256 _amount + ); + + /** + * @notice Emitted when a party has to pay a fee for the dispute or would otherwise be considered as losing. + * @param _transactionId The id of the transaction. + * @param _party The party who has to pay. + */ + event HasToPayFee(uint256 indexed _transactionId, Party _party); + + /** + * @notice Emitted when a party either pays the arbitration fee or gets it reimbursed. + * @param _transactionId The id of the transaction. + * @param _paymentType Whether the party paid or got reimbursed. + * @param _party The party who has paid/got reimbursed the fee. + * @param _amount The amount paid/reimbursed + */ + event ArbitrationFeePayment( + uint256 indexed _transactionId, + ArbitrationFeePaymentType _paymentType, + Party _party, + uint256 _amount + ); + + /** + * @notice Emitted when a ruling is executed. + * @param _transactionId The index of the transaction. + * @param _ruling The given ruling. + */ + event RulingExecuted(uint256 indexed _transactionId, uint256 _ruling); + + /** + * @notice Emitted when a transaction is created. + * @param _transactionId Incremental idenfitifier + * @param _senderId The TL Id of the party paying the escrow amount + * @param _receiverId The TL Id of the intended receiver of the escrow amount + * @param _token The token used for the transaction + * @param _amount The amount of the transaction EXCLUDING FEES + * @param _serviceId The ID of the associated service + * @param _protocolEscrowFeeRate The %fee (per ten thousands) to pay to the protocol's owner + * @param _originServiceFeeRate The %fee (per ten thousands) to pay to the platform on which the transaction was created + * @param _originValidatedProposalFeeRate the %fee (per ten thousands) to pay to the platform on which the validated proposal was created + * @param _arbitrator The address of the contract that can rule on a dispute for the transaction. + * @param _arbitratorExtraData Extra data to set up the arbitration. + * @param _arbitrationFeeTimeout timeout for parties to pay the arbitration fee + */ + event TransactionCreated( + uint256 _transactionId, + uint256 _senderId, + uint256 _receiverId, + address _token, + uint256 _amount, + uint256 _serviceId, + uint256 _proposalId, + uint16 _protocolEscrowFeeRate, + uint16 _originServiceFeeRate, + uint16 _originValidatedProposalFeeRate, + Arbitrator _arbitrator, + bytes _arbitratorExtraData, + uint256 _arbitrationFeeTimeout + ); + + /** + * @notice Emitted when evidence is submitted. + * @param _transactionId The id of the transaction. + * @param _partyId The party submitting the evidence. + * @param _evidenceUri The URI of the evidence. + */ + event EvidenceSubmitted(uint256 indexed _transactionId, uint256 indexed _partyId, string _evidenceUri); + + // =========================== Declarations ============================== + + /** + * @notice Mapping from transactionId to Transactions + */ + mapping(uint256 => Transaction) private transactions; + + /** + * @notice Mapping from platformId to Token address to Token Balance + * Represents the amount of ETH or token present on this contract which + * belongs to a platform and can be withdrawn. + * @dev Id 0 (PROTOCOL_INDEX) is reserved to the protocol balance + * @dev address(0) is reserved to ETH balance + */ + mapping(uint256 => mapping(address => uint256)) private platformIdToTokenToBalance; + + /** + * @notice Instance of TalentLayerService.sol + */ + ITalentLayerService private talentLayerServiceContract; + + /** + * @notice Instance of TalentLayerID.sol + */ + ITalentLayerID private talentLayerIdContract; + + /** + * @notice Instance of TalentLayerPlatformID.sol + */ + ITalentLayerPlatformID private talentLayerPlatformIdContract; + + /** + * @notice (Upgradable) Wallet which will receive the protocol fees + */ + address payable public protocolWallet; + + /** + * @notice Percentage paid to the protocol (per 10,000, upgradable) + */ + uint16 public protocolEscrowFeeRate; + + /** + * @notice The index of the protocol in the "platformIdToTokenToBalance" mapping + */ + uint8 private constant PROTOCOL_INDEX = 0; + + /** + * @notice The fee divider used for every fee rates + */ + uint16 private constant FEE_DIVIDER = 10000; + + /** + * @notice Amount of choices available for ruling the disputes + */ + uint8 constant AMOUNT_OF_CHOICES = 2; + + /** + * @notice Ruling id for sender to win the dispute + */ + uint8 constant SENDER_WINS = 1; + + /** + * @notice Ruling id for receiver to win the dispute + */ + uint8 constant RECEIVER_WINS = 2; + + /** + * @notice One-to-one relationship between the dispute and the transaction. + */ + mapping(uint256 => uint256) public disputeIDtoTransactionID; + + /** + * @notice Platform Id counter + */ + CountersUpgradeable.Counter private nextTransactionId; + + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + _disableInitializers(); + } + + // =========================== Modifiers ============================== + + /** + * @notice Check if the given address is either the owner or the delegate of the given user + * @param _profileId The TalentLayer ID of the user + */ + modifier onlyOwnerOrDelegate(uint256 _profileId) { + require(talentLayerIdContract.isOwnerOrDelegate(_profileId, _msgSender()), "Not owner or delegate"); + _; + } + + // =========================== Initializers ============================== + + /** + * @dev Called on contract deployment + * @param _talentLayerServiceAddress Contract address to TalentLayerService.sol + * @param _talentLayerIDAddress Contract address to TalentLayerID.sol + * @param _talentLayerPlatformIDAddress Contract address to TalentLayerPlatformID.sol + * @param _protocolWallet Wallet used to receive fees + */ + function initialize( + address _talentLayerServiceAddress, + address _talentLayerIDAddress, + address _talentLayerPlatformIDAddress, + address _protocolWallet + ) public initializer { + __Ownable_init(); + __UUPSUpgradeable_init(); + + talentLayerServiceContract = ITalentLayerService(_talentLayerServiceAddress); + talentLayerIdContract = ITalentLayerID(_talentLayerIDAddress); + talentLayerPlatformIdContract = ITalentLayerPlatformID(_talentLayerPlatformIDAddress); + protocolWallet = payable(_protocolWallet); + // Increment counter to start transaction ids at index 1 + nextTransactionId.increment(); + + updateProtocolEscrowFeeRate(100); + } + + // =========================== View functions ============================== + + /** + * @dev Only the owner of the platform ID or the owner can execute this function + * @param _token Token address ("0" for ETH) + * @return balance The balance of the platform or the protocol + */ + function getClaimableFeeBalance(address _token) external view returns (uint256 balance) { + address sender = _msgSender(); + + if (owner() == sender) { + return platformIdToTokenToBalance[PROTOCOL_INDEX][_token]; + } + uint256 platformId = talentLayerPlatformIdContract.ids(sender); + talentLayerPlatformIdContract.isValid(platformId); + return platformIdToTokenToBalance[platformId][_token]; + } + + /** + * @notice Called to get the details of a transaction + * @dev Only the transaction sender or receiver can call this function + * @param _transactionId Id of the transaction + * @return transaction The transaction details + */ + function getTransactionDetails(uint256 _transactionId) external view returns (Transaction memory) { + Transaction memory transaction = transactions[_transactionId]; + require(transaction.id < nextTransactionId.current(), "Invalid transaction id"); + + address sender = _msgSender(); + require( + sender == transaction.sender || sender == transaction.receiver, + "You are not related to this transaction" + ); + return transaction; + } + + // =========================== Owner functions ============================== + + /** + * @notice Updates the Protocol Fee rate + * @dev Only the owner can call this function + * @param _protocolEscrowFeeRate The new protocol fee + */ + function updateProtocolEscrowFeeRate(uint16 _protocolEscrowFeeRate) public onlyOwner { + protocolEscrowFeeRate = _protocolEscrowFeeRate; + emit ProtocolEscrowFeeRateUpdated(_protocolEscrowFeeRate); + } + + /** + * @notice Updates the Protocol wallet that receive fees + * @dev Only the owner can call this function + * @param _protocolWallet The new wallet address + */ + function updateProtocolWallet(address payable _protocolWallet) external onlyOwner { + protocolWallet = _protocolWallet; + } + + /** + * @dev Pauses the creation of transaction, releases and reimbursements. + */ + function pause() external onlyOwner { + _pause(); + } + + /** + * @dev Unpauses the creation of transaction, releases and reimbursements. + */ + function unpause() external onlyOwner { + _unpause(); + } + + // =========================== User functions ============================== + + /** + * @dev Validates a proposal for a service by locking token into escrow. + * @param _serviceId Id of the service that the sender created and the proposal was made for. + * @param _proposalId Id of the proposal that the transaction validates. + * @param _metaEvidence Link to the meta-evidence. + * @param _originDataUri dataURI of the validated proposal + */ + function createTransaction( + uint256 _serviceId, + uint256 _proposalId, + string memory _metaEvidence, + string memory _originDataUri + ) external payable whenNotPaused returns (uint256) { + ( + ITalentLayerService.Service memory service, + ITalentLayerService.Proposal memory proposal + ) = talentLayerServiceContract.getServiceAndProposal(_serviceId, _proposalId); + (address sender, address receiver) = talentLayerIdContract.ownersOf(service.ownerId, proposal.ownerId); + + ITalentLayerPlatformID.Platform memory originServiceCreationPlatform = talentLayerPlatformIdContract + .getPlatform(service.platformId); + ITalentLayerPlatformID.Platform memory originProposalCreationPlatform = service.platformId != + proposal.platformId + ? talentLayerPlatformIdContract.getPlatform(proposal.platformId) + : originServiceCreationPlatform; + + uint256 transactionAmount = _calculateTotalWithFees( + proposal.rateAmount, + originServiceCreationPlatform.originServiceFeeRate, + originProposalCreationPlatform.originValidatedProposalFeeRate + ); + + if (proposal.rateToken == address(0)) { + require(msg.value == transactionAmount, "Non-matching funds"); + } else { + require(msg.value == 0, "Non-matching funds"); + } + + require(_msgSender() == sender, "Access denied"); + require(proposal.ownerId == _proposalId, "Incorrect proposal ID"); + require(proposal.expirationDate >= block.timestamp, "Proposal expired"); + require(service.status == ITalentLayerService.Status.Opened, "Service status not open"); + require(proposal.status == ITalentLayerService.ProposalStatus.Pending, "Proposal status not pending"); + require(bytes(_metaEvidence).length == 46, "Invalid cid"); + require( + keccak256(abi.encodePacked(proposal.dataUri)) == keccak256(abi.encodePacked(_originDataUri)), + "Proposal dataUri has changed" + ); + + uint256 transactionId = nextTransactionId.current(); + transactions[transactionId] = Transaction({ + id: transactionId, + sender: sender, + receiver: receiver, + token: service.token, + amount: proposal.rateAmount, + releasedAmount: 0, + serviceId: _serviceId, + proposalId: _proposalId, + protocolEscrowFeeRate: protocolEscrowFeeRate, + originServiceFeeRate: originServiceCreationPlatform.originServiceFeeRate, + originValidatedProposalFeeRate: originProposalCreationPlatform.originValidatedProposalFeeRate, + disputeId: 0, + senderFee: 0, + receiverFee: 0, + lastInteraction: block.timestamp, + status: Status.NoDispute, + arbitrator: originServiceCreationPlatform.arbitrator, + arbitratorExtraData: originServiceCreationPlatform.arbitratorExtraData, + arbitrationFeeTimeout: originServiceCreationPlatform.arbitrationFeeTimeout + }); + + nextTransactionId.increment(); + + talentLayerServiceContract.afterDeposit(_serviceId, _proposalId, transactionId); + + if (proposal.rateToken != address(0)) { + IERC20Upgradeable(proposal.rateToken).safeTransferFrom(sender, address(this), transactionAmount); + } + + _afterCreateTransaction(service.ownerId, proposal.ownerId, transactionId, _metaEvidence); + + return transactionId; + } + + /** + * @notice Allows the sender to release locked-in escrow value to the intended recipient. + * The amount released must not include the fees. + * @param _profileId The TalentLayer ID of the user + * @param _transactionId Id of the transaction to release escrow value for. + * @param _amount Value to be released without fees. Should not be more than amount locked in. + */ + function release( + uint256 _profileId, + uint256 _transactionId, + uint256 _amount + ) external whenNotPaused onlyOwnerOrDelegate(_profileId) { + _validatePayment(_transactionId, PaymentType.Release, _profileId, _amount); + + Transaction storage transaction = transactions[_transactionId]; + transaction.amount -= _amount; + transaction.releasedAmount += _amount; + + _release(_transactionId, _amount); + } + + /** + * @notice Allows the intended receiver to return locked-in escrow value back to the sender. + * The amount reimbursed must not include the fees. + * @param _profileId The TalentLayer ID of the user + * @param _transactionId Id of the transaction to reimburse escrow value for. + * @param _amount Value to be reimbursed without fees. Should not be more than amount locked in. + */ + function reimburse( + uint256 _profileId, + uint256 _transactionId, + uint256 _amount + ) external whenNotPaused onlyOwnerOrDelegate(_profileId) { + _validatePayment(_transactionId, PaymentType.Reimburse, _profileId, _amount); + + Transaction storage transaction = transactions[_transactionId]; + transaction.amount -= _amount; + + _reimburse(_transactionId, _amount); + } + + /** + * @notice Allows the sender of the transaction to pay the arbitration fee to raise a dispute. + * Note that the arbitrator can have createDispute throw, which will make this function throw and therefore lead to a party being timed-out. + * This is not a vulnerability as the arbitrator can rule in favor of one party anyway. + * @param _transactionId Id of the transaction. + */ + function payArbitrationFeeBySender(uint256 _transactionId) public payable { + Transaction storage transaction = transactions[_transactionId]; + + require(address(transaction.arbitrator) != address(0), "Arbitrator not set"); + require( + transaction.status < Status.DisputeCreated, + "Dispute has already been created or because the transaction has been executed" + ); + require(_msgSender() == transaction.sender, "The caller must be the sender"); + + uint256 arbitrationCost = transaction.arbitrator.arbitrationCost(transaction.arbitratorExtraData); + transaction.senderFee += msg.value; + // The total fees paid by the sender should be at least the arbitration cost. + require(transaction.senderFee == arbitrationCost, "The sender fee must be equal to the arbitration cost"); + + transaction.lastInteraction = block.timestamp; + + emit ArbitrationFeePayment(_transactionId, ArbitrationFeePaymentType.Pay, Party.Sender, msg.value); + + // The receiver still has to pay. This can also happen if he has paid, but arbitrationCost has increased. + if (transaction.receiverFee < arbitrationCost) { + transaction.status = Status.WaitingReceiver; + emit HasToPayFee(_transactionId, Party.Receiver); + } else { + // The receiver has also paid the fee. We create the dispute. + _raiseDispute(_transactionId, arbitrationCost); + } + } + + /** + * @notice Allows the receiver of the transaction to pay the arbitration fee to raise a dispute. + * Note that this function mirrors payArbitrationFeeBySender. + * @param _transactionId Id of the transaction. + */ + function payArbitrationFeeByReceiver(uint256 _transactionId) public payable { + Transaction storage transaction = transactions[_transactionId]; + + require(address(transaction.arbitrator) != address(0), "Arbitrator not set"); + require( + transaction.status < Status.DisputeCreated, + "Dispute has already been created or because the transaction has been executed" + ); + require(_msgSender() == transaction.receiver, "The caller must be the receiver"); + + uint256 arbitrationCost = transaction.arbitrator.arbitrationCost(transaction.arbitratorExtraData); + transaction.receiverFee += msg.value; + // The total fees paid by the receiver should be at least the arbitration cost. + require(transaction.receiverFee == arbitrationCost, "The receiver fee must be equal to the arbitration cost"); + + transaction.lastInteraction = block.timestamp; + + emit ArbitrationFeePayment(_transactionId, ArbitrationFeePaymentType.Pay, Party.Receiver, msg.value); + + // The sender still has to pay. This can also happen if he has paid, but arbitrationCost has increased. + if (transaction.senderFee < arbitrationCost) { + transaction.status = Status.WaitingSender; + emit HasToPayFee(_transactionId, Party.Sender); + } else { + // The sender has also paid the fee. We create the dispute. + _raiseDispute(_transactionId, arbitrationCost); + } + } + + /** + * @notice If one party fails to pay the arbitration fee in time, the other can call this function and will win the case + * @param _transactionId Id of the transaction. + */ + function arbitrationFeeTimeout(uint256 _transactionId) public { + Transaction storage transaction = transactions[_transactionId]; + + require( + block.timestamp - transaction.lastInteraction >= transaction.arbitrationFeeTimeout, + "Timeout time has not passed yet" + ); + + if (transaction.status == Status.WaitingSender) { + if (transaction.senderFee != 0) { + uint256 senderFee = transaction.senderFee; + transaction.senderFee = 0; + payable(transaction.sender).call{value: senderFee}(""); + } + _executeRuling(_transactionId, RECEIVER_WINS); + } else if (transaction.status == Status.WaitingReceiver) { + if (transaction.receiverFee != 0) { + uint256 receiverFee = transaction.receiverFee; + transaction.receiverFee = 0; + payable(transaction.receiver).call{value: receiverFee}(""); + } + _executeRuling(_transactionId, SENDER_WINS); + } + } + + /** + * @notice Allows a party to submit a reference to evidence. + * @param _profileId The TalentLayer ID of the user + * @param _transactionId The index of the transaction. + * @param _evidence A link to an evidence using its URI. + */ + function submitEvidence( + uint256 _profileId, + uint256 _transactionId, + string memory _evidence + ) public onlyOwnerOrDelegate(_profileId) { + require(bytes(_evidence).length == 46, "Invalid cid"); + Transaction storage transaction = transactions[_transactionId]; + + require(address(transaction.arbitrator) != address(0), "Arbitrator not set"); + + address party = talentLayerIdContract.ownerOf(_profileId); + require( + party == transaction.sender || party == transaction.receiver, + "The caller must be the sender or the receiver or their delegates" + ); + require(transaction.status < Status.Resolved, "Must not send evidence if the dispute is resolved"); + + emit Evidence(transaction.arbitrator, _transactionId, party, _evidence); + emit EvidenceSubmitted(_transactionId, _profileId, _evidence); + } + + /** + * @notice Appeals an appealable ruling, paying the appeal fee to the arbitrator. + * Note that no checks are required as the checks are done by the arbitrator. + * + * @param _transactionId Id of the transaction. + */ + function appeal(uint256 _transactionId) public payable { + Transaction storage transaction = transactions[_transactionId]; + + require(address(transaction.arbitrator) != address(0), "Arbitrator not set"); + + transaction.arbitrator.appeal{value: msg.value}(transaction.disputeId, transaction.arbitratorExtraData); + } + + // =========================== Platform functions ============================== + + /** + * @notice Allows a platform owner to claim its tokens & / or ETH balance. + * @param _platformId The ID of the platform claiming the balance. + * @param _tokenAddress The address of the Token contract (address(0) if balance in ETH). + * Emits a BalanceTransferred event + */ + function claim(uint256 _platformId, address _tokenAddress) external whenNotPaused { + address payable recipient; + + if (owner() == _msgSender()) { + require(_platformId == PROTOCOL_INDEX, "Access denied"); + recipient = protocolWallet; + } else { + talentLayerPlatformIdContract.isValid(_platformId); + recipient = payable(talentLayerPlatformIdContract.ownerOf(_platformId)); + } + + uint256 amount = platformIdToTokenToBalance[_platformId][_tokenAddress]; + require(amount > 0, "nothing to claim"); + platformIdToTokenToBalance[_platformId][_tokenAddress] = 0; + _safeTransferBalance(recipient, _tokenAddress, amount); + + emit FeesClaimed(_platformId, _tokenAddress, amount); + } + + // =========================== Arbitrator functions ============================== + + /** + * @notice Allows the arbitrator to give a ruling for a dispute. + * @param _disputeID The ID of the dispute in the Arbitrator contract. + * @param _ruling Ruling given by the arbitrator. Note that 0 is reserved for "Not able/wanting to make a decision". + */ + function rule(uint256 _disputeID, uint256 _ruling) public { + address sender = _msgSender(); + uint256 transactionId = disputeIDtoTransactionID[_disputeID]; + Transaction storage transaction = transactions[transactionId]; + + require(sender == address(transaction.arbitrator), "The caller must be the arbitrator"); + require(transaction.status == Status.DisputeCreated, "The dispute has already been resolved"); + + emit Ruling(Arbitrator(sender), _disputeID, _ruling); + + _executeRuling(transactionId, _ruling); + } + + // =========================== Internal functions ============================== + + /** + * @notice Creates a dispute, paying the arbitration fee to the arbitrator. Parties are refund if + * they overpaid for the arbitration fee. + * @param _transactionId Id of the transaction. + * @param _arbitrationCost Amount to pay the arbitrator. + */ + function _raiseDispute(uint256 _transactionId, uint256 _arbitrationCost) internal { + Transaction storage transaction = transactions[_transactionId]; + transaction.status = Status.DisputeCreated; + Arbitrator arbitrator = transaction.arbitrator; + + transaction.disputeId = arbitrator.createDispute{value: _arbitrationCost}( + AMOUNT_OF_CHOICES, + transaction.arbitratorExtraData + ); + disputeIDtoTransactionID[transaction.disputeId] = _transactionId; + emit Dispute(arbitrator, transaction.disputeId, _transactionId, _transactionId); + + // Refund sender if it overpaid. + if (transaction.senderFee > _arbitrationCost) { + uint256 extraFeeSender = transaction.senderFee - _arbitrationCost; + transaction.senderFee = _arbitrationCost; + payable(transaction.sender).call{value: extraFeeSender}(""); + emit ArbitrationFeePayment(_transactionId, ArbitrationFeePaymentType.Reimburse, Party.Sender, msg.value); + } + + // Refund receiver if it overpaid. + if (transaction.receiverFee > _arbitrationCost) { + uint256 extraFeeReceiver = transaction.receiverFee - _arbitrationCost; + transaction.receiverFee = _arbitrationCost; + payable(transaction.receiver).call{value: extraFeeReceiver}(""); + emit ArbitrationFeePayment(_transactionId, ArbitrationFeePaymentType.Reimburse, Party.Receiver, msg.value); + } + } + + /** + * @notice Executes a ruling of a dispute. Sends the funds and reimburses the arbitration fee to the winning party. + * @param _transactionId The index of the transaction. + * @param _ruling Ruling given by the arbitrator. + * 0: Refused to rule, split amount equally between sender and receiver. + * 1: Reimburse the sender + * 2: Pay the receiver + */ + function _executeRuling(uint256 _transactionId, uint256 _ruling) internal { + Transaction storage transaction = transactions[_transactionId]; + require(_ruling <= AMOUNT_OF_CHOICES, "Invalid ruling"); + + address payable sender = payable(transaction.sender); + address payable receiver = payable(transaction.receiver); + uint256 amount = transaction.amount; + uint256 senderFee = transaction.senderFee; + uint256 receiverFee = transaction.receiverFee; + + transaction.amount = 0; + transaction.senderFee = 0; + transaction.receiverFee = 0; + transaction.status = Status.Resolved; + + // Send the funds to the winner and reimburse the arbitration fee. + if (_ruling == SENDER_WINS) { + sender.call{value: senderFee}(""); + _reimburse(_transactionId, amount); + } else if (_ruling == RECEIVER_WINS) { + receiver.call{value: receiverFee}(""); + _release(_transactionId, amount); + } else { + // If no ruling is given split funds in half + uint256 splitFeeAmount = senderFee / 2; + uint256 splitTransactionAmount = amount / 2; + + _reimburse(_transactionId, splitTransactionAmount); + _release(_transactionId, splitTransactionAmount); + + sender.call{value: splitFeeAmount}(""); + receiver.call{value: splitFeeAmount}(""); + } + + emit RulingExecuted(_transactionId, _ruling); + } + + /** + * @notice Function that revert when `_msgSender()` is not authorized to upgrade the contract. Called by + * {upgradeTo} and {upgradeToAndCall}. + * @param newImplementation address of the new contract implementation + */ + function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} + + // =========================== Private functions ============================== + + /** + * @notice Emits the events related to the creation of a transaction. + * @param _senderId The TL ID of the sender + * @param _receiverId The TL ID of the receiver + * @param _transactionId The ID of the transaction + * @param _metaEvidence The meta evidence of the transaction + */ + function _afterCreateTransaction( + uint256 _senderId, + uint256 _receiverId, + uint256 _transactionId, + string memory _metaEvidence + ) internal { + Transaction storage transaction = transactions[_transactionId]; + + emit TransactionCreated( + _transactionId, + _senderId, + _receiverId, + transaction.token, + transaction.amount, + transaction.serviceId, + transaction.proposalId, + protocolEscrowFeeRate, + transaction.originServiceFeeRate, + transaction.originValidatedProposalFeeRate, + transaction.arbitrator, + transaction.arbitratorExtraData, + transaction.arbitrationFeeTimeout + ); + emit MetaEvidence(_transactionId, _metaEvidence); + } + + /** + * @notice Used to release part of the escrow payment to the receiver. + * @dev The release of an amount will also trigger the release of the fees to the platform's balances & the protocol fees. + * @param _transactionId The transaction to release the escrow value for + * @param _amount The amount to release + */ + function _release(uint256 _transactionId, uint256 _amount) private { + _distributeFees(_transactionId, _amount); + + Transaction storage transaction = transactions[_transactionId]; + _safeTransferBalance(payable(transaction.receiver), transaction.token, _amount); + + _afterPayment(_transactionId, PaymentType.Release, _amount); + } + + /** + * @notice Used to reimburse part of the escrow payment to the sender. + * @dev Fees linked to the amount reimbursed will be automatically calculated and send back to the sender in the same transfer + * @param _transactionId The transaction + * @param _amount The amount to reimburse without fees + */ + function _reimburse(uint256 _transactionId, uint256 _amount) private { + Transaction storage transaction = transactions[_transactionId]; + uint256 totalReleaseAmount = _calculateTotalWithFees( + _amount, + transaction.originServiceFeeRate, + transaction.originValidatedProposalFeeRate + ); + _safeTransferBalance(payable(transaction.sender), transaction.token, totalReleaseAmount); + + _afterPayment(_transactionId, PaymentType.Reimburse, _amount); + } + + /** + * @notice Distribute fees to the platform's balances & the protocol after a fund release + * @param _transactionId The transaction linked to the payment + * @param _releaseAmount The amount released + */ + function _distributeFees(uint256 _transactionId, uint256 _releaseAmount) private { + Transaction storage transaction = transactions[_transactionId]; + ( + ITalentLayerService.Service memory service, + ITalentLayerService.Proposal memory proposal + ) = talentLayerServiceContract.getServiceAndProposal(transaction.serviceId, transaction.proposalId); + + uint256 originServiceCreationPlatformId = service.platformId; + uint256 originValidatedProposalPlatformId = proposal.platformId; + + uint256 protocolEscrowFeeRateAmount = (transaction.protocolEscrowFeeRate * _releaseAmount) / FEE_DIVIDER; + uint256 originServiceFeeRate = (transaction.originServiceFeeRate * _releaseAmount) / FEE_DIVIDER; + uint256 originValidatedProposalFeeRate = (transaction.originValidatedProposalFeeRate * _releaseAmount) / + FEE_DIVIDER; + + platformIdToTokenToBalance[PROTOCOL_INDEX][transaction.token] += protocolEscrowFeeRateAmount; + platformIdToTokenToBalance[originServiceCreationPlatformId][transaction.token] += originServiceFeeRate; + platformIdToTokenToBalance[originValidatedProposalPlatformId][ + transaction.token + ] += originValidatedProposalFeeRate; + + emit OriginServiceFeeRateReleased( + originServiceCreationPlatformId, + transaction.serviceId, + transaction.token, + originServiceFeeRate + ); + emit OriginValidatedProposalFeeRateReleased( + originValidatedProposalPlatformId, + transaction.serviceId, + transaction.token, + originServiceFeeRate + ); + } + + /** + * @notice Used to validate a release or a reimburse payment + * @param _transactionId The transaction linked to the payment + * @param _paymentType The type of payment to validate + * @param _profileId The profileId of the msgSender + * @param _amount The amount to release + */ + function _validatePayment( + uint256 _transactionId, + PaymentType _paymentType, + uint256 _profileId, + uint256 _amount + ) private view { + Transaction storage _transaction = transactions[_transactionId]; + if (_paymentType == PaymentType.Release) { + require(_transaction.sender == talentLayerIdContract.ownerOf(_profileId), "Access denied"); + } else if (_paymentType == PaymentType.Reimburse) { + require(_transaction.receiver == talentLayerIdContract.ownerOf(_profileId), "Access denied"); + } + + require(_transaction.id < nextTransactionId.current(), "Invalid transaction id"); + require(_transaction.status == Status.NoDispute, "The transaction shouldn't be disputed"); + require(_transaction.amount >= _amount, "Insufficient funds"); + require(_amount >= FEE_DIVIDER || (_amount < FEE_DIVIDER && _amount == _transaction.amount), "Amount too low"); + } + + /** + * @notice Used to trigger events after a payment and to complete a service when the payment is full + * @param _transactionId The transaction linked to the payment + * @param _paymentType The type of the payment + * @param _releaseAmount The amount of the transaction + */ + function _afterPayment(uint256 _transactionId, PaymentType _paymentType, uint256 _releaseAmount) private { + Transaction storage transaction = transactions[_transactionId]; + emit Payment(transaction.id, _paymentType, transaction.token, _releaseAmount, transaction.serviceId); + + if (transaction.amount == 0) { + talentLayerServiceContract.afterFullPayment(transaction.serviceId, transaction.releasedAmount); + emit PaymentCompleted(transaction.serviceId); + } + } + + /** + * @notice Used to transfer the token or ETH balance from the escrow contract to a recipient's address. + * @param _recipient The address to transfer the balance to + * @param _tokenAddress The token address + * @param _amount The amount to transfer + */ + function _safeTransferBalance(address payable _recipient, address _tokenAddress, uint256 _amount) private { + if (address(0) == _tokenAddress) { + _recipient.call{value: _amount}(""); + } else { + IERC20(_tokenAddress).transfer(_recipient, _amount); + } + } + + /** + * @notice Utility function to calculate the total amount to be paid by the buyer to validate a proposal. + * @param _amount The core escrow amount + * @param _originServiceFeeRate the %fee (per ten thousands) asked by the platform for each service created on the platform + * @param _originValidatedProposalFeeRate the %fee (per ten thousands) asked by the platform for each validates service on the platform + * @return totalEscrowAmount The total amount to be paid by the buyer (including all fees + escrow) The amount to transfer + */ + function _calculateTotalWithFees( + uint256 _amount, + uint16 _originServiceFeeRate, + uint16 _originValidatedProposalFeeRate + ) private view returns (uint256 totalEscrowAmount) { + return + _amount + + (((_amount * protocolEscrowFeeRate) + + (_amount * _originServiceFeeRate) + + (_amount * _originValidatedProposalFeeRate)) / FEE_DIVIDER); + } + + // =========================== Overrides ============================== + + function _msgSender() + internal + view + virtual + override(ContextUpgradeable, ERC2771RecipientUpgradeable) + returns (address) + { + return ERC2771RecipientUpgradeable._msgSender(); + } + + function _msgData() + internal + view + virtual + override(ContextUpgradeable, ERC2771RecipientUpgradeable) + returns (bytes calldata) + { + return ERC2771RecipientUpgradeable._msgData(); + } +} From 25d5f65915185c32b00fcd71c869795cc5689191 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 31 May 2023 14:39:27 +0100 Subject: [PATCH 03/99] Added new functions in TalentLayerServiceV2.sol Signed-off-by: Quentin D.C --- contracts/Upgrades/TalentLayerEscrowV2.sol | 6 +- contracts/Upgrades/TalentLayerServiceV2.sol | 36 +++ contracts/interfaces/ITalentLayerService.sol | 2 + test/batch/fullWorkflow.ts | 254 ++++++------------- test/utils/deploy.ts | 24 +- 5 files changed, 139 insertions(+), 183 deletions(-) diff --git a/contracts/Upgrades/TalentLayerEscrowV2.sol b/contracts/Upgrades/TalentLayerEscrowV2.sol index b0ce414c..6c037ed9 100644 --- a/contracts/Upgrades/TalentLayerEscrowV2.sol +++ b/contracts/Upgrades/TalentLayerEscrowV2.sol @@ -469,7 +469,7 @@ contract TalentLayerEscrowV2 is originProposalCreationPlatform.originValidatedProposalFeeRate ); - if (proposal.rateToken == address(0)) { + if (service.token == address(0)) { require(msg.value == transactionAmount, "Non-matching funds"); } else { require(msg.value == 0, "Non-matching funds"); @@ -513,8 +513,8 @@ contract TalentLayerEscrowV2 is talentLayerServiceContract.afterDeposit(_serviceId, _proposalId, transactionId); - if (proposal.rateToken != address(0)) { - IERC20Upgradeable(proposal.rateToken).safeTransferFrom(sender, address(this), transactionAmount); + if (service.token != address(0)) { + IERC20Upgradeable(service.token).safeTransferFrom(sender, address(this), transactionAmount); } _afterCreateTransaction(service.ownerId, proposal.ownerId, transactionId, _metaEvidence); diff --git a/contracts/Upgrades/TalentLayerServiceV2.sol b/contracts/Upgrades/TalentLayerServiceV2.sol index 33f3c148..2d04bcf1 100644 --- a/contracts/Upgrades/TalentLayerServiceV2.sol +++ b/contracts/Upgrades/TalentLayerServiceV2.sol @@ -153,6 +153,26 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP uint256 expirationDate ); + /** + * @notice Emitted after a new proposal is created + * @param serviceId The service id + * @param ownerId The talentLayerId of the seller who made the proposal + * @param dataUri token Id to IPFS URI mapping + * @param status proposal status + * @param rateAmount the amount of token chosen + * @param platformId the platform ID on which the proposal was created + * @param expirationDate the timeout for the proposal + */ + event ProposalCreatedWithoutToken( + uint256 serviceId, + uint256 ownerId, + string dataUri, + ProposalStatus status, + uint256 rateAmount, + uint256 platformId, + uint256 expirationDate + ); + /** * @notice Emitted after an existing proposal has been updated * @param serviceId The service id @@ -171,6 +191,22 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP uint256 expirationDate ); + /** + * @notice Emitted after an existing proposal has been updated + * @param serviceId The service id + * @param ownerId The talentLayerId of the seller who made the proposal + * @param dataUri token Id to IPFS URI mapping + * @param rateAmount the amount of token chosen + * @param expirationDate the timeout for the proposal + */ + event ProposalUpdatedWithoutToken( + uint256 serviceId, + uint256 ownerId, + string dataUri, + uint256 rateAmount, + uint256 expirationDate + ); + /** * @notice Emitted when the contract owner adds or removes a token from the allowed payment tokens list * @param tokenAddress The address of the payment token diff --git a/contracts/interfaces/ITalentLayerService.sol b/contracts/interfaces/ITalentLayerService.sol index c5359bc0..761e25da 100644 --- a/contracts/interfaces/ITalentLayerService.sol +++ b/contracts/interfaces/ITalentLayerService.sol @@ -26,6 +26,8 @@ interface ITalentLayerService { string dataUri; uint256 transactionId; uint256 platformId; + address token; + uint256 referralAmount; } struct Proposal { diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index 5469708c..6232d36b 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -32,7 +32,7 @@ const carolTlId = 3 const alicePlatformId = 1 const bobPlatformId = 2 -describe('TalentLayer protocol global testing', function () { +describe.only('TalentLayer protocol global testing', function () { // we define the types of the variables we will use let deployer: SignerWithAddress, alice: SignerWithAddress, @@ -58,6 +58,7 @@ describe('TalentLayer protocol global testing', function () { chainId: number const nonListedRateToken = '0x6b175474e89094c44da98b954eedeac495271d0f' + // const rateToken = ethers.constants.AddressZero const rateToken = '0xC01FcDfDE3B2ABA1eab76731493C617FfAED2F10' before(async function () { @@ -71,7 +72,7 @@ describe('TalentLayer protocol global testing', function () { talentLayerService, talentLayerReview, token, - ] = await deploy(false) + ] = await deploy(true) // Grant Platform Id Mint role to Deployer and Bob const mintRole = await talentLayerPlatformID.MINT_ROLE() @@ -741,14 +742,18 @@ describe('TalentLayer protocol global testing', function () { it("Dave, who doesn't have TalentLayerID, can't create a service", async function () { const signature = await getSignatureForService(platformOneOwner, 0, 0, 'haveNotTlid') await expect( - talentLayerService.connect(dave).createService(0, 1, 'haveNotTlid', signature), + talentLayerService + .connect(dave) + .createService(0, 1, 'haveNotTlid', signature, token.address), ).to.be.revertedWith('ERC721: invalid token ID') }) it("Alice can't create a new service with a talentLayerPlatformId 0", async function () { const signature = await getSignatureForService(platformOneOwner, 0, 0, cid) await expect( - talentLayerService.connect(alice).createService(aliceTlId, 0, cid, signature), + talentLayerService + .connect(alice) + .createService(aliceTlId, 0, cid, signature, token.address), ).to.be.revertedWith('Invalid platform ID') }) @@ -759,13 +764,27 @@ describe('TalentLayer protocol global testing', function () { const signature = await getSignatureForService(platformOneOwner, aliceTlId, 0, cid) const tx = talentLayerService .connect(alice) - .createService(aliceTlId, alicePlatformId, cid, signature, { + .createService(aliceTlId, alicePlatformId, cid, signature, token.address, { value: alicePlatformServicePostingFee.sub(1), }) await expect(tx).to.be.revertedWith('Non-matching funds') }) + it('Should revert if Carol tries to create a service with a non-whitelisted payment token', async function () { + const platform = await talentLayerPlatformID.getPlatform(alicePlatformId) + const alicePlatformServicePostingFee = platform.servicePostingFee + + const signature = await getSignatureForService(platformOneOwner, aliceTlId, 0, cid) + const tx = talentLayerService + .connect(alice) + .createService(aliceTlId, alicePlatformId, cid, signature, nonListedRateToken, { + value: alicePlatformServicePostingFee, + }) + + await expect(tx).to.be.revertedWith('Token not allowed') + }) + it('Alice the buyer can create a few Open service', async function () { const platform = await talentLayerPlatformID.getPlatform(alicePlatformId) const alicePlatformServicePostingFee = platform.servicePostingFee @@ -774,16 +793,16 @@ describe('TalentLayer protocol global testing', function () { const signature = await getSignatureForService(platformOneOwner, aliceTlId, 0, cid) await talentLayerService .connect(alice) - .createService(aliceTlId, alicePlatformId, cid, signature, { + .createService(aliceTlId, alicePlatformId, cid, signature, token.address, { value: alicePlatformServicePostingFee, }) - const serviceData = await talentLayerService.services(1) + const service1Data = await talentLayerService.services(1) // service 2 const signature2 = await getSignatureForService(platformOneOwner, aliceTlId, 1, cid) await talentLayerService .connect(alice) - .createService(aliceTlId, alicePlatformId, cid, signature2, { + .createService(aliceTlId, alicePlatformId, cid, signature2, token.address, { value: alicePlatformServicePostingFee, }) await talentLayerService.services(2) @@ -792,7 +811,7 @@ describe('TalentLayer protocol global testing', function () { const signature3 = await getSignatureForService(platformOneOwner, aliceTlId, 2, cid) await talentLayerService .connect(alice) - .createService(aliceTlId, alicePlatformId, cid, signature3, { + .createService(aliceTlId, alicePlatformId, cid, signature3, ethers.constants.AddressZero, { value: alicePlatformServicePostingFee, }) await talentLayerService.services(3) @@ -801,7 +820,7 @@ describe('TalentLayer protocol global testing', function () { const signature4 = await getSignatureForService(platformOneOwner, aliceTlId, 3, cid) await talentLayerService .connect(alice) - .createService(aliceTlId, alicePlatformId, cid, signature4, { + .createService(aliceTlId, alicePlatformId, cid, signature4, token.address, { value: alicePlatformServicePostingFee, }) await talentLayerService.services(4) @@ -810,21 +829,23 @@ describe('TalentLayer protocol global testing', function () { const signature5 = await getSignatureForService(platformOneOwner, aliceTlId, 4, cid) await talentLayerService .connect(alice) - .createService(aliceTlId, alicePlatformId, cid, signature5, { + .createService(aliceTlId, alicePlatformId, cid, signature5, token.address, { value: alicePlatformServicePostingFee, }) await talentLayerService.services(5) - expect(serviceData.status).to.be.equal(ServiceStatus.Opened) - expect(serviceData.ownerId).to.be.equal(aliceTlId) - expect(serviceData.dataUri).to.be.equal(cid) - expect(serviceData.platformId).to.be.equal(1) + expect(service1Data.status).to.be.equal(ServiceStatus.Opened) + expect(service1Data.ownerId).to.be.equal(aliceTlId) + expect(service1Data.dataUri).to.be.equal(cid) + expect(service1Data.platformId).to.be.equal(1) }) it("Alice can't create a new open service with wrong TalentLayer Platform ID", async function () { const signature = await getSignatureForService(platformOneOwner, aliceTlId, 5, cid) await expect( - talentLayerService.connect(alice).createService(aliceTlId, 5, 'wrongTlPid', signature), + talentLayerService + .connect(alice) + .createService(aliceTlId, 5, 'wrongTlPid', signature, token.address), ).to.be.revertedWith('Invalid platform ID') }) @@ -853,19 +874,9 @@ describe('TalentLayer protocol global testing', function () { const signature = await getSignatureForProposal(platformOneOwner, aliceTlId, 1, cid) const tx = talentLayerService .connect(alice) - .createProposal( - aliceTlId, - 1, - rateToken, - 15, - alicePlatformId, - cid, - proposalExpirationDate, - signature, - { - value: alicePlatformProposalPostingFee, - }, - ) + .createProposal(aliceTlId, 1, 15, alicePlatformId, cid, proposalExpirationDate, signature, { + value: alicePlatformProposalPostingFee, + }) await expect(tx).to.be.revertedWith("can't create for your own service") }) @@ -877,16 +888,7 @@ describe('TalentLayer protocol global testing', function () { await expect( talentLayerService .connect(bob) - .createProposal( - bobTlId, - 5, - rateToken, - 15, - bobPlatformId, - cid, - proposalExpirationDate, - signature, - ), + .createProposal(bobTlId, 5, 15, bobPlatformId, cid, proposalExpirationDate, signature), ).to.be.revertedWith('Service not opened') }) @@ -899,7 +901,7 @@ describe('TalentLayer protocol global testing', function () { it('Bob cannot update his proposal since it does not exist yet', async function () { const tx = talentLayerService .connect(bob) - .updateProposal(bobTlId, 1, rateToken, 18, cid, proposalExpirationDate) + .updateProposal(bobTlId, 1, 18, cid, proposalExpirationDate) await expect(tx).to.be.revertedWith('Not the owner') }) @@ -915,19 +917,9 @@ describe('TalentLayer protocol global testing', function () { await expect( talentLayerService .connect(bob) - .createProposal( - bobTlId, - 1, - rateToken, - 9, - alicePlatformId, - cid, - proposalExpirationDate, - signature, - { - value: alicePlatformProposalPostingFee, - }, - ), + .createProposal(bobTlId, 1, 9, alicePlatformId, cid, proposalExpirationDate, signature, { + value: alicePlatformProposalPostingFee, + }), ).to.be.revertedWith('Amount too low') }) @@ -939,19 +931,9 @@ describe('TalentLayer protocol global testing', function () { const signature = await getSignatureForProposal(platformOneOwner, bobTlId, 1, cid2) const tx = talentLayerService .connect(bob) - .createProposal( - bobTlId, - 1, - rateToken, - 15, - alicePlatformId, - cid2, - proposalExpirationDate, - signature, - { - value: alicePlatformProposalPostingFee.sub(1), - }, - ) + .createProposal(bobTlId, 1, 15, alicePlatformId, cid2, proposalExpirationDate, signature, { + value: alicePlatformProposalPostingFee.sub(1), + }) await expect(tx).to.be.revertedWith('Non-matching funds') }) @@ -970,19 +952,9 @@ describe('TalentLayer protocol global testing', function () { const signature = await getSignatureForProposal(platformOneOwner, bobTlId, 1, cid2) await talentLayerService .connect(bob) - .createProposal( - bobTlId, - 1, - rateToken, - 15, - alicePlatformId, - cid2, - proposalExpirationDate, - signature, - { - value: alicePlatformProposalPostingFee, - }, - ) + .createProposal(bobTlId, 1, 15, alicePlatformId, cid2, proposalExpirationDate, signature, { + value: alicePlatformProposalPostingFee, + }) const serviceData = await talentLayerService.services(1) const proposalDataAfter = await talentLayerService.getProposal(1, bobTid) @@ -992,8 +964,8 @@ describe('TalentLayer protocol global testing', function () { expect(serviceData.ownerId).to.be.equal(aliceTlId) // Proposal data check after the proposal - - expect(proposalDataAfter.rateToken).to.be.equal(rateToken) + // @dev: rateToken field not used any more + expect(proposalDataAfter.rateToken).to.be.equal(ethers.constants.AddressZero) expect(proposalDataAfter.rateAmount.toString()).to.be.equal('15') expect(proposalDataAfter.dataUri).to.be.equal(cid2) expect(proposalDataAfter.ownerId).to.be.equal(bobTlId) @@ -1008,19 +980,9 @@ describe('TalentLayer protocol global testing', function () { const signature = await getSignatureForProposal(platformOneOwner, bobTlId, 1, cid2) const tx = talentLayerService .connect(bob) - .createProposal( - bobTlId, - 1, - rateToken, - 15, - alicePlatformId, - cid2, - proposalExpirationDate, - signature, - { - value: alicePlatformProposalPostingFee, - }, - ) + .createProposal(bobTlId, 1, 15, alicePlatformId, cid2, proposalExpirationDate, signature, { + value: alicePlatformProposalPostingFee, + }) await expect(tx).to.be.revertedWith('proposal already exist') }) @@ -1035,22 +997,12 @@ describe('TalentLayer protocol global testing', function () { const signature = await getSignatureForProposal(platformOneOwner, eveTid.toNumber(), 1, cid2) await talentLayerService .connect(eve) - .createProposal( - eveTid, - 1, - rateToken, - 15, - alicePlatformId, - cid2, - expiredProposalDate, - signature, - { - value: alicePlatformProposalPostingFee, - }, - ) + .createProposal(eveTid, 1, 15, alicePlatformId, cid2, expiredProposalDate, signature, { + value: alicePlatformProposalPostingFee, + }) }) - it('Alice should note be able to validate the Eve proposal after the expiration date', async function () { + it('Alice should not be able to validate the Eve proposal after the expiration date', async function () { await expect( talentLayerEscrow.connect(alice).createTransaction(1, 4, metaEvidenceCid, cid2), ).to.be.revertedWith('Proposal expired') @@ -1064,54 +1016,22 @@ describe('TalentLayer protocol global testing', function () { const signature = await getSignatureForProposal(bob, carolTlId, 1, cid2) await talentLayerService .connect(carol) - .createProposal( - carolTlId, - 1, - rateToken, - 16, - bobPlatformId, - cid2, - proposalExpirationDate, - signature, - { - value: bobPlatformProposalPostingFee, - }, - ) + .createProposal(carolTlId, 1, 16, bobPlatformId, cid2, proposalExpirationDate, signature, { + value: bobPlatformProposalPostingFee, + }) await talentLayerService.services(1) // get proposal info const carolTid = await talentLayerID.ids(carol.address) await talentLayerService.getProposal(1, carolTid) }) - it('Should revert if Carol tries to create a proposal with a non-whitelisted payment token', async function () { - const platform = await talentLayerPlatformID.getPlatform(alicePlatformId) - const alicePlatformProposalPostingFee = platform.proposalPostingFee - - const signature = await getSignatureForProposal(platformOneOwner, carolTlId, 1, cid2) - await expect( - talentLayerService - .connect(carol) - .createProposal( - carolTlId, - 1, - nonListedRateToken, - 16, - alicePlatformId, - cid2, - proposalExpirationDate, - signature, - { value: alicePlatformProposalPostingFee }, - ), - ).to.be.revertedWith('Token not allowed') - }) - it('Bob can update his first proposal ', async function () { const proposalDataBefore = await talentLayerService.getProposal(1, bobTlId) expect(proposalDataBefore.rateAmount.toString()).to.be.equal('15') await talentLayerService .connect(bob) - .updateProposal(bobTlId, 1, rateToken, 18, cid, proposalExpirationDate) + .updateProposal(bobTlId, 1, 18, cid, proposalExpirationDate) const proposalDataAfter = await talentLayerService.getProposal(1, bobTlId) expect(proposalDataAfter.rateAmount.toString()).to.be.equal('18') @@ -1120,30 +1040,22 @@ describe('TalentLayer protocol global testing', function () { it("Bob can't update his proposal with an amount which is too low", async function () { const minTransactionAmount = await ( - await talentLayerService.allowedTokenList(rateToken) + await talentLayerService.allowedTokenList(token.address) ).minimumTransactionAmount const tx = talentLayerService .connect(bob) - .updateProposal( - bobTlId, - 1, - rateToken, - minTransactionAmount.sub(1), - cid, - proposalExpirationDate, - ) + .updateProposal(bobTlId, 1, minTransactionAmount.sub(1), cid, proposalExpirationDate) await expect(tx).to.be.revertedWith('Amount too low') }) - it('Should revert if Bob updates his proposal with a non-whitelisted payment token ', async function () { - await expect( - talentLayerService - .connect(bob) - .updateProposal(bobTlId, 1, nonListedRateToken, 2, cid2, proposalExpirationDate), - ).to.be.revertedWith('Token not allowed') - }) + //TODO do same with service + // it('Should revert if Bob updates his proposal with a non-whitelisted payment token ', async function () { + // await expect( + // talentLayerService.connect(bob).updateProposal(bobTlId, 1, 2, cid2, proposalExpirationDate), + // ).to.be.revertedWith('Token not allowed') + // }) }) describe('Escrow Contract test.', function () { @@ -1178,7 +1090,6 @@ describe('TalentLayer protocol global testing', function () { .createProposal( bobTlId, serviceId, - token.address, amountBob, bobPlatformId, cid, @@ -1200,7 +1111,6 @@ describe('TalentLayer protocol global testing', function () { .createProposal( carolTlId, serviceId, - token.address, amountCarol, bobPlatformId, cid, @@ -1218,7 +1128,6 @@ describe('TalentLayer protocol global testing', function () { .createProposal( carolTlId, 99, - ethers.constants.AddressZero, 1000, bobPlatformId, cid, @@ -1253,6 +1162,7 @@ describe('TalentLayer protocol global testing', function () { }) it("Alice can deposit funds for Bob's proposal, which will emit an event.", async function () { + const service = await talentLayerService.services(serviceId) await talentLayerPlatformID.connect(alice).updateOriginServiceFeeRate(alicePlatformId, 1100) await talentLayerPlatformID .connect(bob) @@ -1321,7 +1231,6 @@ describe('TalentLayer protocol global testing', function () { .createProposal( carolTlId, serviceId, - rateToken, 15, alicePlatformId, cid2, @@ -1338,7 +1247,7 @@ describe('TalentLayer protocol global testing', function () { it('Bob cannot update his proposal after the service is confirmed', async function () { const tx = talentLayerService .connect(bob) - .updateProposal(bobTlId, serviceId, rateToken, 18, cid, proposalExpirationDate) + .updateProposal(bobTlId, serviceId, 18, cid, proposalExpirationDate) await expect(tx).to.be.revertedWith('Service not opened') }) @@ -1485,9 +1394,11 @@ describe('TalentLayer protocol global testing', function () { // Create the service const serviceId = 6 const signature = await getSignatureForService(platformOneOwner, aliceTlId, 5, cid) - await talentLayerService.connect(alice).createService(aliceTlId, 1, cid, signature, { - value: alicePlatformServicePostingFee, - }) + await talentLayerService + .connect(alice) + .createService(aliceTlId, 1, cid, signature, token.address, { + value: alicePlatformServicePostingFee, + }) await talentLayerService.services(serviceId) // Create the proposal @@ -1498,7 +1409,6 @@ describe('TalentLayer protocol global testing', function () { .createProposal( bobTlId, serviceId, - rateToken, 15, alicePlatformId, cid, @@ -1668,7 +1578,6 @@ describe('TalentLayer protocol global testing', function () { .createProposal( bobTlId, serviceId, - ethAddress, amountBob, bobPlatformId, cid, @@ -1689,7 +1598,6 @@ describe('TalentLayer protocol global testing', function () { .createProposal( carolTlId, serviceId, - ethAddress, amountCarol, bobPlatformId, cid, @@ -1699,11 +1607,11 @@ describe('TalentLayer protocol global testing', function () { ) }) - // bob will try to frunt run the proposal by changing the proposal dataUri + // bob will try to front run the proposal by changing the proposal dataUri it('Bob will try to front run the proposal validation by changing the proposal dataUri.', async function () { await talentLayerService .connect(bob) - .updateProposal(bobTlId, serviceId, ethAddress, amountBob, cid2, proposalExpirationDate) + .updateProposal(bobTlId, serviceId, amountBob, cid2, proposalExpirationDate) await expect( talentLayerEscrow diff --git a/test/utils/deploy.ts b/test/utils/deploy.ts index 1ee36842..bcbf7077 100644 --- a/test/utils/deploy.ts +++ b/test/utils/deploy.ts @@ -37,12 +37,12 @@ export async function deploy( // Deploy TalentLayerID const TalentLayerID = await ethers.getContractFactory('TalentLayerID') const talentLayerIDArgs: [string] = [talentLayerPlatformID.address] - let talentLayerID = await upgrades.deployProxy(TalentLayerID, talentLayerIDArgs) + const talentLayerID = await upgrades.deployProxy(TalentLayerID, talentLayerIDArgs) - if (applyUpgrade) { - const TalentLayerIDV2 = await ethers.getContractFactory('TalentLayerIDV2') - talentLayerID = await upgrades.upgradeProxy(talentLayerID.address, TalentLayerIDV2) - } + // if (applyUpgrade) { + // const TalentLayerIDV2 = await ethers.getContractFactory('TalentLayerIDV2') + // talentLayerID = await upgrades.upgradeProxy(talentLayerID.address, TalentLayerIDV2) + // } // Deploy TalentLayerService const TalentLayerService = await ethers.getContractFactory('TalentLayerService') @@ -50,7 +50,7 @@ export async function deploy( talentLayerID.address, talentLayerPlatformID.address, ] - const talentLayerService = await upgrades.deployProxy(TalentLayerService, talentLayerServiceArgs) + let talentLayerService = await upgrades.deployProxy(TalentLayerService, talentLayerServiceArgs) // Deploy TalentLayerArbitrator const TalentLayerArbitrator = await ethers.getContractFactory('TalentLayerArbitrator') @@ -64,7 +64,7 @@ export async function deploy( talentLayerPlatformID.address, networkConfig.multisigAddressList.fee, ] - const talentLayerEscrow = await upgrades.deployProxy(TalentLayerEscrow, TalentLayerEscrowArgs) + let talentLayerEscrow = await upgrades.deployProxy(TalentLayerEscrow, TalentLayerEscrowArgs) const escrowRole = await talentLayerService.ESCROW_ROLE() await talentLayerService.grantRole(escrowRole, talentLayerEscrow.address) @@ -80,6 +80,16 @@ export async function deploy( const SimpleERC20 = await ethers.getContractFactory('SimpleERC20') const simpleERC20 = await SimpleERC20.deploy() + if (applyUpgrade) { + const talentLayerEscrowV2 = await ethers.getContractFactory('TalentLayerEscrowV2') + talentLayerEscrow = await upgrades.upgradeProxy(talentLayerEscrow.address, talentLayerEscrowV2) + const talentLayerServiceV2 = await ethers.getContractFactory('TalentLayerServiceV2') + talentLayerService = await upgrades.upgradeProxy( + talentLayerService.address, + talentLayerServiceV2, + ) + } + return [ talentLayerID as TalentLayerID, talentLayerPlatformID as TalentLayerPlatformID, From a71195c65cbb8a59a20177c76f2bb902619a6ce8 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 31 May 2023 14:43:19 +0100 Subject: [PATCH 04/99] Added new functions in TalentLayerServiceV2.sol Signed-off-by: Quentin D.C --- contracts/Upgrades/TalentLayerServiceV2.sol | 39 +++++++++------------ 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/contracts/Upgrades/TalentLayerServiceV2.sol b/contracts/Upgrades/TalentLayerServiceV2.sol index 2d04bcf1..f64a1439 100644 --- a/contracts/Upgrades/TalentLayerServiceV2.sol +++ b/contracts/Upgrades/TalentLayerServiceV2.sol @@ -65,7 +65,7 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP * @param status the current status of a service * @param ownerId the talentLayerId of the seller * @param rateToken the token choose for the payment - * @param rateAmount the amount of token chosen + * @param DEPRECATED - rateAmount the amount of token chosen * @param dataUri token Id to IPFS URI mapping * @param expirationDate the timeout for the proposal */ @@ -357,14 +357,16 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP * @param _platformId platform ID on which the Service token was created * @param _dataUri IPFS URI of the offchain data of the service * @param _signature optional platform signature to allow the operation + * @param _token token address to be used for the service's payments */ function createService( uint256 _profileId, uint256 _platformId, string calldata _dataUri, - bytes calldata _signature + bytes calldata _signature, + address _token ) public payable onlyOwnerOrDelegate(_profileId) returns (uint256) { - _validateService(_profileId, _platformId, _dataUri, _signature); + _validateService(_profileId, _platformId, _dataUri, _signature, _token); uint256 id = nextServiceId; nextServiceId++; @@ -374,6 +376,7 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP service.ownerId = _profileId; service.dataUri = _dataUri; service.platformId = _platformId; + service.token = _token; if (serviceNonce[_profileId] == 0 && proposalNonce[_profileId] == 0) { tlId.setHasActivity(_profileId); @@ -402,7 +405,7 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP address _token, uint256 _referralAmount ) public payable onlyOwnerOrDelegate(_profileId) returns (uint256) { - _validateService(_profileId, _platformId, _dataUri, _signature); + _validateService(_profileId, _platformId, _dataUri, _signature, _token); uint256 id = nextServiceId; nextServiceId++; @@ -429,7 +432,6 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP * @notice Allows an seller to propose his service for a service * @param _profileId The TalentLayer ID of the user owner of the proposal * @param _serviceId The service linked to the new proposal - * @param _rateToken the token choose for the payment * @param _rateAmount the amount of token chosen * @param _dataUri token Id to IPFS URI mapping * @param _platformId platform ID from where the proposal is created @@ -439,19 +441,18 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP function createProposal( uint256 _profileId, uint256 _serviceId, - address _rateToken, uint256 _rateAmount, uint256 _platformId, string calldata _dataUri, uint256 _expirationDate, bytes calldata _signature ) public payable onlyOwnerOrDelegate(_profileId) { - _validateProposal(_profileId, _serviceId, _rateToken, _rateAmount, _platformId, _dataUri, _signature); + _validateProposal(_profileId, _serviceId, _rateAmount, _platformId, _dataUri, _signature); proposals[_serviceId][_profileId] = Proposal({ status: ProposalStatus.Pending, ownerId: _profileId, - rateToken: _rateToken, + rateToken: address(0), rateAmount: _rateAmount, platformId: _platformId, dataUri: _dataUri, @@ -463,12 +464,11 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP } proposalNonce[_profileId]++; - emit ProposalCreated( + emit ProposalCreatedWithoutToken( _serviceId, _profileId, _dataUri, ProposalStatus.Pending, - _rateToken, _rateAmount, _platformId, _expirationDate @@ -479,7 +479,6 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP * @notice Allows the owner to update his own proposal for a given service * @param _profileId The TalentLayer ID of the user * @param _serviceId The service linked to the new proposal - * @param _rateToken the token choose for the payment * @param _rateAmount the amount of token chosen * @param _dataUri token Id to IPFS URI mapping * @param _expirationDate the time before the proposal is automatically validated @@ -487,27 +486,23 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP function updateProposal( uint256 _profileId, uint256 _serviceId, - address _rateToken, uint256 _rateAmount, string calldata _dataUri, uint256 _expirationDate ) public onlyOwnerOrDelegate(_profileId) { - require(allowedTokenList[_rateToken].isWhitelisted, "Token not allowed"); - Service storage service = services[_serviceId]; Proposal storage proposal = proposals[_serviceId][_profileId]; require(service.status == Status.Opened, "Service not opened"); require(proposal.ownerId == _profileId, "Not the owner"); require(bytes(_dataUri).length == 46, "Invalid cid"); require(proposal.status != ProposalStatus.Validated, "Already validated"); - require(_rateAmount >= allowedTokenList[_rateToken].minimumTransactionAmount, "Amount too low"); + require(_rateAmount >= allowedTokenList[service.token].minimumTransactionAmount, "Amount too low"); - proposal.rateToken = _rateToken; proposal.rateAmount = _rateAmount; proposal.dataUri = _dataUri; proposal.expirationDate = _expirationDate; - emit ProposalUpdated(_serviceId, _profileId, _dataUri, _rateToken, _rateAmount, _expirationDate); + emit ProposalUpdatedWithoutToken(_serviceId, _profileId, _dataUri, _rateAmount, _expirationDate); } /** @@ -652,11 +647,13 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP uint256 _profileId, uint256 _platformId, string calldata _dataUri, - bytes calldata _signature + bytes calldata _signature, + address _token ) private view { uint256 servicePostingFee = talentLayerPlatformIdContract.getServicePostingFee(_platformId); require(msg.value == servicePostingFee, "Non-matching funds"); require(bytes(_dataUri).length == 46, "Invalid cid"); + require(allowedTokenList[_token].isWhitelisted, "Token not allowed"); address platformSigner = talentLayerPlatformIdContract.getSigner(_platformId); if (platformSigner != address(0)) { @@ -671,7 +668,6 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP * @notice Validate a new proposal * @param _profileId The TalentLayer ID of the user * @param _serviceId The service linked to the new proposal - * @param _rateToken the token choose for the payment * @param _rateAmount the amount of token chosen * @param _platformId platform ID on which the Proposal was created * @param _dataUri token Id to IPFS URI mapping @@ -680,22 +676,19 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP function _validateProposal( uint256 _profileId, uint256 _serviceId, - address _rateToken, uint256 _rateAmount, uint256 _platformId, string calldata _dataUri, bytes calldata _signature ) private view { - require(allowedTokenList[_rateToken].isWhitelisted, "Token not allowed"); uint256 proposalPostingFee = talentLayerPlatformIdContract.getProposalPostingFee(_platformId); require(msg.value == proposalPostingFee, "Non-matching funds"); - require(_rateAmount >= allowedTokenList[_rateToken].minimumTransactionAmount, "Amount too low"); Service storage service = services[_serviceId]; + require(_rateAmount >= allowedTokenList[service.token].minimumTransactionAmount, "Amount too low"); require(service.status == Status.Opened, "Service not opened"); require(service.ownerId != 0, "Service not exist"); require(proposals[_serviceId][_profileId].ownerId != _profileId, "proposal already exist"); - // require(service.token == _rateToken, "Non-matching tokens"); require(service.ownerId != _profileId, "can't create for your own service"); require(bytes(_dataUri).length == 46, "Invalid cid"); From 1683046d06a1ead9e6741e7419f982eeba7fc84d Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 31 May 2023 14:48:12 +0100 Subject: [PATCH 05/99] Removed fields from tests Signed-off-by: Quentin D.C --- test/batch/fullWorkflow.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index 6232d36b..e4da0ea3 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -32,7 +32,7 @@ const carolTlId = 3 const alicePlatformId = 1 const bobPlatformId = 2 -describe.only('TalentLayer protocol global testing', function () { +describe('TalentLayer protocol global testing', function () { // we define the types of the variables we will use let deployer: SignerWithAddress, alice: SignerWithAddress, @@ -58,7 +58,6 @@ describe.only('TalentLayer protocol global testing', function () { chainId: number const nonListedRateToken = '0x6b175474e89094c44da98b954eedeac495271d0f' - // const rateToken = ethers.constants.AddressZero const rateToken = '0xC01FcDfDE3B2ABA1eab76731493C617FfAED2F10' before(async function () { @@ -1162,7 +1161,6 @@ describe.only('TalentLayer protocol global testing', function () { }) it("Alice can deposit funds for Bob's proposal, which will emit an event.", async function () { - const service = await talentLayerService.services(serviceId) await talentLayerPlatformID.connect(alice).updateOriginServiceFeeRate(alicePlatformId, 1100) await talentLayerPlatformID .connect(bob) From 7407a5234afec0fcebe5269bacee6baf9596bb72 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 31 May 2023 15:12:50 +0100 Subject: [PATCH 06/99] Updated updateService function Signed-off-by: Quentin D.C --- contracts/Upgrades/TalentLayerServiceV2.sol | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/contracts/Upgrades/TalentLayerServiceV2.sol b/contracts/Upgrades/TalentLayerServiceV2.sol index f64a1439..049e8038 100644 --- a/contracts/Upgrades/TalentLayerServiceV2.sol +++ b/contracts/Upgrades/TalentLayerServiceV2.sol @@ -567,19 +567,26 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP * @notice Update Service URI data * @param _profileId The TalentLayer ID of the user, owner of the service * @param _serviceId, Service ID to update + * @param _referralAmount, New referral amount + * @param _token, New token address * @param _dataUri New IPFS URI */ - function updateServiceData( + function updateService( uint256 _profileId, uint256 _serviceId, + uint256 _referralAmount, + address _token, string calldata _dataUri ) public onlyOwnerOrDelegate(_profileId) { Service storage service = services[_serviceId]; require(service.ownerId == _profileId, "Not the owner"); require(service.status == Status.Opened, "status must be opened"); + require(allowedTokenList[_token].isWhitelisted, "Token not allowed"); require(bytes(_dataUri).length == 46, "Invalid cid"); service.dataUri = _dataUri; + service.referralAmount = _referralAmount; + service.token = _token; emit ServiceDetailedUpdated(_serviceId, _dataUri); } From d083d9c4e478fee04ba568ea4c65cb2ffdb67d5e Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 31 May 2023 15:13:12 +0100 Subject: [PATCH 07/99] Updated tests Signed-off-by: Quentin D.C --- test/batch/fullWorkflow.ts | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index e4da0ea3..f88c0f66 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -58,7 +58,7 @@ describe('TalentLayer protocol global testing', function () { chainId: number const nonListedRateToken = '0x6b175474e89094c44da98b954eedeac495271d0f' - const rateToken = '0xC01FcDfDE3B2ABA1eab76731493C617FfAED2F10' + const referralAmount = 2 before(async function () { // Get the Signers @@ -849,11 +849,21 @@ describe('TalentLayer protocol global testing', function () { }) it('Alice can update her service data', async function () { - await talentLayerService.connect(alice).updateServiceData(aliceTlId, 1, cid2) + await talentLayerService + .connect(alice) + .updateService(aliceTlId, 1, referralAmount, token.address, cid2) const serviceData = await talentLayerService.services(1) expect(serviceData.dataUri).to.be.equal(cid2) }) + it('Alice cannot update her service with a non-whitelisted token', async function () { + await expect( + talentLayerService + .connect(alice) + .updateService(aliceTlId, 1, referralAmount, nonListedRateToken, cid2), + ).to.be.revertedWith('Token not allowed') + }) + it('Alice can cancel her own service', async function () { await talentLayerService.connect(alice).cancelService(aliceTlId, 5) const serviceData = await talentLayerService.services(5) @@ -1048,13 +1058,6 @@ describe('TalentLayer protocol global testing', function () { await expect(tx).to.be.revertedWith('Amount too low') }) - - //TODO do same with service - // it('Should revert if Bob updates his proposal with a non-whitelisted payment token ', async function () { - // await expect( - // talentLayerService.connect(bob).updateProposal(bobTlId, 1, 2, cid2, proposalExpirationDate), - // ).to.be.revertedWith('Token not allowed') - // }) }) describe('Escrow Contract test.', function () { @@ -1209,7 +1212,9 @@ describe('TalentLayer protocol global testing', function () { }) it('Alice cannot update her service data after it is confirmed', async function () { - const tx = talentLayerService.connect(alice).updateServiceData(aliceTlId, serviceId, cid2) + const tx = talentLayerService + .connect(alice) + .updateService(aliceTlId, serviceId, referralAmount, token.address, cid2) await expect(tx).to.be.revertedWith('status must be opened') }) From b630bc54d5e8b7c5beea33f733cb6f4b582ed53f Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 31 May 2023 15:46:58 +0100 Subject: [PATCH 08/99] Updated delegation tests Signed-off-by: Quentin D.C --- test/batch/delegationSystem.ts | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/test/batch/delegationSystem.ts b/test/batch/delegationSystem.ts index 67cf868f..06fd4072 100644 --- a/test/batch/delegationSystem.ts +++ b/test/batch/delegationSystem.ts @@ -25,6 +25,7 @@ const serviceId = 1 const trasactionId = 1 const transactionAmount = 100000 const ethAddress = '0x0000000000000000000000000000000000000000' +const referralAmount = 0 /** * Deploys contracts and sets up the context for TalentLayerId contract. @@ -43,7 +44,7 @@ async function deployAndSetup( , talentLayerService, talentLayerReview, - ] = await deploy(false) + ] = await deploy(true) // Deployer whitelists a list of authorized tokens await talentLayerService @@ -74,7 +75,7 @@ async function deployAndSetup( ] } -describe('Delegation System', function () { +describe.only('Delegation System', function () { let alice: SignerWithAddress, bob: SignerWithAddress, carol: SignerWithAddress, @@ -131,19 +132,21 @@ describe('Delegation System', function () { const signature = await getSignatureForService(platformOneOwner, aliceTlId, 0, cid) const tx = talentLayerService .connect(eve) - .createService(aliceTlId, carolPlatformId, cid, signature) + .createService(aliceTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero) await expect(tx).to.be.revertedWith('Not owner or delegate') await talentLayerService .connect(dave) - .createService(aliceTlId, carolPlatformId, cid, signature) + .createService(aliceTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero) const serviceData = await talentLayerService.services(1) expect(serviceData.ownerId.toNumber()).to.be.equal(aliceTlId) }) it('Dave can update service data on behalf of Alice', async function () { - const tx = await talentLayerService.connect(dave).updateServiceData(aliceTlId, serviceId, cid) + const tx = await talentLayerService + .connect(dave) + .updateService(aliceTlId, serviceId, referralAmount, ethers.constants.AddressZero, cid) await expect(tx).to.not.be.reverted }) @@ -154,7 +157,6 @@ describe('Delegation System', function () { .createProposal( bobTlId, serviceId, - ethAddress, transactionAmount, carolPlatformId, cid, @@ -168,14 +170,7 @@ describe('Delegation System', function () { it('Eve can update a proposal on behalf of Bob', async function () { const tx = await talentLayerService .connect(eve) - .updateProposal( - bobTlId, - serviceId, - ethAddress, - transactionAmount, - cid, - proposalExpirationDate, - ) + .updateProposal(bobTlId, serviceId, transactionAmount, cid, proposalExpirationDate) await expect(tx).to.not.be.reverted }) @@ -239,7 +234,7 @@ describe('Delegation System', function () { const signature = await getSignatureForService(platformOneOwner, aliceTlId, 1, cid) const tx = talentLayerService .connect(dave) - .createService(aliceTlId, carolPlatformId, cid, signature) + .createService(aliceTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero) await expect(tx).to.be.revertedWith('Not owner or delegate') }) }) From f3bfa512089ea79b8de4f6dfa6407554f67fbc84 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 31 May 2023 19:38:02 +0100 Subject: [PATCH 09/99] Updated audit tests Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 12 ++++++------ contracts/TalentLayerPlatformID.sol | 6 +++--- test/manual/audit.ts | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index 77578756..ec65218f 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -469,7 +469,7 @@ contract TalentLayerEscrow is originProposalCreationPlatform.originValidatedProposalFeeRate ); - if (proposal.rateToken == address(0)) { + if (service.token == address(0)) { require(msg.value == transactionAmount, "Non-matching funds"); } else { require(msg.value == 0, "Non-matching funds"); @@ -491,7 +491,7 @@ contract TalentLayerEscrow is id: transactionId, sender: sender, receiver: receiver, - token: proposal.rateToken, + token: service.token, amount: proposal.rateAmount, releasedAmount: 0, serviceId: _serviceId, @@ -513,8 +513,8 @@ contract TalentLayerEscrow is talentLayerServiceContract.afterDeposit(_serviceId, _proposalId, transactionId); - if (proposal.rateToken != address(0)) { - IERC20Upgradeable(proposal.rateToken).safeTransferFrom(sender, address(this), transactionAmount); + if (service.token != address(0)) { + IERC20Upgradeable(service.token).safeTransferFrom(sender, address(this), transactionAmount); } _afterCreateTransaction(service.ownerId, proposal.ownerId, transactionId, _metaEvidence); @@ -844,7 +844,7 @@ contract TalentLayerEscrow is * @notice Emits the events related to the creation of a transaction. * @param _senderId The TL ID of the sender * @param _receiverId The TL ID of the receiver - * @param _transactionId The ID of the transavtion + * @param _transactionId The ID of the transaction * @param _metaEvidence The meta evidence of the transaction */ function _afterCreateTransaction( @@ -947,7 +947,7 @@ contract TalentLayerEscrow is } /** - * @notice Used to validate a realease or a reimburse payment + * @notice Used to validate a release or a reimburse payment * @param _transactionId The transaction linked to the payment * @param _paymentType The type of payment to validate * @param _profileId The profileId of the msgSender diff --git a/contracts/TalentLayerPlatformID.sol b/contracts/TalentLayerPlatformID.sol index 710b90f5..ce314578 100644 --- a/contracts/TalentLayerPlatformID.sol +++ b/contracts/TalentLayerPlatformID.sol @@ -101,7 +101,7 @@ contract TalentLayerPlatformID is ERC721Upgradeable, AccessControlUpgradeable, U bytes32 public constant MINT_ROLE = keccak256("MINT_ROLE"); /** - * @notice Minimum timeout to pay arbitration fee + * @notice Minimum timeout to pay arbitration fee in seconds */ uint256 public minArbitrationFeeTimeout; @@ -214,9 +214,9 @@ contract TalentLayerPlatformID is ERC721Upgradeable, AccessControlUpgradeable, U } /** - * @notice Allows retrieval of a Platform arbitrator + * @notice Allows retrieval of a Platform * @param _platformId The Platform Id - * @return Arbitrator The Platform arbitrator + * @return Platform The Platform */ function getPlatform(uint256 _platformId) external view returns (Platform memory) { isValid(_platformId); diff --git a/test/manual/audit.ts b/test/manual/audit.ts index 0f75f7d2..5eddb596 100644 --- a/test/manual/audit.ts +++ b/test/manual/audit.ts @@ -42,7 +42,7 @@ async function deployAndSetup(): Promise< talentLayerService, talentLayerReview, simpleERC20, - ] = await deploy(false) + ] = await deploy(true) // Deployer mints Platform Id for Carol const platformName = 'hirevibes' From d72be64b7e5075e4a2611f76456f36c1a4ed4754 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 31 May 2023 19:38:08 +0100 Subject: [PATCH 10/99] Updated load tests Signed-off-by: Quentin D.C --- test/manual/loadTest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/manual/loadTest.ts b/test/manual/loadTest.ts index 86fb7b3e..2d23583d 100644 --- a/test/manual/loadTest.ts +++ b/test/manual/loadTest.ts @@ -50,7 +50,7 @@ describe('Load test', function () { talentLayerEscrow, talentLayerArbitrator, talentLayerService, - ] = await deploy(false) + ] = await deploy(true) // Grant Platform Id Mint role to Alice const mintRole = await talentLayerPlatformID.MINT_ROLE() From fe78b13905bd781f81a7a667f7a21773e13bbb22 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 31 May 2023 19:38:21 +0100 Subject: [PATCH 11/99] Updated platform verification tests Signed-off-by: Quentin D.C --- test/batch/platformVerification.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/test/batch/platformVerification.ts b/test/batch/platformVerification.ts index 574cf528..cb343cb0 100644 --- a/test/batch/platformVerification.ts +++ b/test/batch/platformVerification.ts @@ -44,7 +44,7 @@ async function deployAndSetup(): Promise< talentLayerService, talentLayerReview, simpleERC20, - ] = await deploy(false) + ] = await deploy(true) // Deployer mints Platform Id for Carol const platformName = 'hirevibes' @@ -119,7 +119,7 @@ describe('Platform verification', function () { const tx = talentLayerService .connect(alice) - .createService(aliceTlId, carolPlatformId, cid, signature) + .createService(aliceTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero) await expect(tx).to.not.reverted }) @@ -129,7 +129,7 @@ describe('Platform verification', function () { const tx = talentLayerService .connect(bob) - .createService(bobTlId, carolPlatformId, cid, signature) + .createService(bobTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero) await expect(tx).to.revertedWith('invalid signature') }) @@ -139,7 +139,7 @@ describe('Platform verification', function () { const tx = talentLayerService .connect(bob) - .createService(bobTlId, carolPlatformId, cid, signature) + .createService(bobTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero) await expect(tx).to.revertedWith('invalid signature') }) @@ -149,7 +149,7 @@ describe('Platform verification', function () { const tx = talentLayerService .connect(bob) - .createService(bobTlId, carolPlatformId, cid, signature) + .createService(bobTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero) await expect(tx).to.revertedWith('invalid signature') }) @@ -159,7 +159,7 @@ describe('Platform verification', function () { const tx = talentLayerService .connect(alice) - .createService(aliceTlId, carolPlatformId, cid, signature) + .createService(aliceTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero) await expect(tx).to.revertedWith('invalid signature') }) @@ -169,7 +169,7 @@ describe('Platform verification', function () { const tx = talentLayerService .connect(alice) - .createService(aliceTlId, carolPlatformId, cid, signature) + .createService(aliceTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero) await expect(tx).to.not.reverted }) @@ -183,7 +183,6 @@ describe('Platform verification', function () { .createProposal( bobTlId, serviceId, - ethers.constants.AddressZero, 1, carolPlatformId, cid, @@ -209,7 +208,7 @@ describe('Platform verification', function () { const tx = await talentLayerService .connect(alice) - .createService(aliceTlId, carolPlatformId, cid, signature) + .createService(aliceTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero) await expect(tx).to.not.reverted }) @@ -227,7 +226,6 @@ describe('Platform verification', function () { .createProposal( bobTlId, serviceId, - ethers.constants.AddressZero, 1, carolPlatformId, cid, From 4e3e1c6f72102bfde9e8f2b221fb114645df2bc8 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 31 May 2023 19:38:29 +0100 Subject: [PATCH 12/99] Updated pausable escrow verification tests Signed-off-by: Quentin D.C --- test/batch/pausableEscrow.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/batch/pausableEscrow.ts b/test/batch/pausableEscrow.ts index 70448aef..b487f592 100644 --- a/test/batch/pausableEscrow.ts +++ b/test/batch/pausableEscrow.ts @@ -68,7 +68,9 @@ async function deployAndSetup(): Promise< // Alice, the buyer, initiates a new open service const signature = await getSignatureForService(carol, aliceTlId, 0, cid) - await talentLayerService.connect(alice).createService(aliceTlId, carolPlatformId, cid, signature) + await talentLayerService + .connect(alice) + .createService(aliceTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero) // Bob, the seller, creates a proposal for the service const signature2 = await getSignatureForProposal(carol, bobTlId, serviceId, cid) @@ -77,7 +79,6 @@ async function deployAndSetup(): Promise< .createProposal( bobTlId, serviceId, - tokenAddress, transactionAmount, carolPlatformId, cid, From 2265b076fea90c99d5fb1c8a3f900301b78d932d Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 31 May 2023 19:38:41 +0100 Subject: [PATCH 13/99] Updated delegation tests Signed-off-by: Quentin D.C --- test/batch/delegationSystem.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/batch/delegationSystem.ts b/test/batch/delegationSystem.ts index 06fd4072..67b011ce 100644 --- a/test/batch/delegationSystem.ts +++ b/test/batch/delegationSystem.ts @@ -75,7 +75,7 @@ async function deployAndSetup( ] } -describe.only('Delegation System', function () { +describe('Delegation System', function () { let alice: SignerWithAddress, bob: SignerWithAddress, carol: SignerWithAddress, From e5ae8681e4fc0653a312ba106f237099d58b9af2 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 31 May 2023 19:40:17 +0100 Subject: [PATCH 14/99] Revers commit on original contracts Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 12 ++++++------ contracts/TalentLayerPlatformID.sol | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index ec65218f..77578756 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -469,7 +469,7 @@ contract TalentLayerEscrow is originProposalCreationPlatform.originValidatedProposalFeeRate ); - if (service.token == address(0)) { + if (proposal.rateToken == address(0)) { require(msg.value == transactionAmount, "Non-matching funds"); } else { require(msg.value == 0, "Non-matching funds"); @@ -491,7 +491,7 @@ contract TalentLayerEscrow is id: transactionId, sender: sender, receiver: receiver, - token: service.token, + token: proposal.rateToken, amount: proposal.rateAmount, releasedAmount: 0, serviceId: _serviceId, @@ -513,8 +513,8 @@ contract TalentLayerEscrow is talentLayerServiceContract.afterDeposit(_serviceId, _proposalId, transactionId); - if (service.token != address(0)) { - IERC20Upgradeable(service.token).safeTransferFrom(sender, address(this), transactionAmount); + if (proposal.rateToken != address(0)) { + IERC20Upgradeable(proposal.rateToken).safeTransferFrom(sender, address(this), transactionAmount); } _afterCreateTransaction(service.ownerId, proposal.ownerId, transactionId, _metaEvidence); @@ -844,7 +844,7 @@ contract TalentLayerEscrow is * @notice Emits the events related to the creation of a transaction. * @param _senderId The TL ID of the sender * @param _receiverId The TL ID of the receiver - * @param _transactionId The ID of the transaction + * @param _transactionId The ID of the transavtion * @param _metaEvidence The meta evidence of the transaction */ function _afterCreateTransaction( @@ -947,7 +947,7 @@ contract TalentLayerEscrow is } /** - * @notice Used to validate a release or a reimburse payment + * @notice Used to validate a realease or a reimburse payment * @param _transactionId The transaction linked to the payment * @param _paymentType The type of payment to validate * @param _profileId The profileId of the msgSender diff --git a/contracts/TalentLayerPlatformID.sol b/contracts/TalentLayerPlatformID.sol index ce314578..710b90f5 100644 --- a/contracts/TalentLayerPlatformID.sol +++ b/contracts/TalentLayerPlatformID.sol @@ -101,7 +101,7 @@ contract TalentLayerPlatformID is ERC721Upgradeable, AccessControlUpgradeable, U bytes32 public constant MINT_ROLE = keccak256("MINT_ROLE"); /** - * @notice Minimum timeout to pay arbitration fee in seconds + * @notice Minimum timeout to pay arbitration fee */ uint256 public minArbitrationFeeTimeout; @@ -214,9 +214,9 @@ contract TalentLayerPlatformID is ERC721Upgradeable, AccessControlUpgradeable, U } /** - * @notice Allows retrieval of a Platform + * @notice Allows retrieval of a Platform arbitrator * @param _platformId The Platform Id - * @return Platform The Platform + * @return Arbitrator The Platform arbitrator */ function getPlatform(uint256 _platformId) external view returns (Platform memory) { isValid(_platformId); From 035a39207977989a4303d28208d9233267026ba9 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Thu, 1 Jun 2023 07:58:49 +0100 Subject: [PATCH 15/99] Updated serviceCompletion.ts tests Signed-off-by: Quentin D.C --- test/batch/serviceCompletion.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/batch/serviceCompletion.ts b/test/batch/serviceCompletion.ts index 5b8b734e..d8bca8c4 100644 --- a/test/batch/serviceCompletion.ts +++ b/test/batch/serviceCompletion.ts @@ -129,7 +129,7 @@ describe('Completion of service', function () { ) await talentLayerService .connect(alice) - .createService(aliceTlId, carolPlatformId, cid, signatureService) + .createService(aliceTlId, carolPlatformId, cid, signatureService, tokenAddress) // Bob, the seller, creates a proposal for the service const signatureProposal = await getSignatureForProposal(carol, bobTlId, serviceId, cid) @@ -138,7 +138,6 @@ describe('Completion of service', function () { .createProposal( bobTlId, serviceId, - tokenAddress, transactionAmount, carolPlatformId, cid, From 338c460e0444224b79b342ae347870bf0acba74d Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Thu, 1 Jun 2023 08:16:02 +0100 Subject: [PATCH 16/99] Updated disputeResolution.ts tests & fixed a bug Signed-off-by: Quentin D.C --- test/batch/disputeResolution.ts | 55 ++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/test/batch/disputeResolution.ts b/test/batch/disputeResolution.ts index bb96e865..201cd5d1 100644 --- a/test/batch/disputeResolution.ts +++ b/test/batch/disputeResolution.ts @@ -99,7 +99,9 @@ async function deployAndSetup( // Alice, the buyer, initiates a new open service const signature = await getSignatureForService(carol, aliceTlId, 0, cid) - await talentLayerService.connect(alice).createService(aliceTlId, carolPlatformId, cid, signature) + await talentLayerService + .connect(alice) + .createService(aliceTlId, carolPlatformId, cid, signature, tokenAddress) // Bob, the seller, creates a proposal for the service const signature2 = await getSignatureForProposal(carol, bobTlId, serviceId, cid) @@ -108,7 +110,6 @@ async function deployAndSetup( .createProposal( bobTlId, serviceId, - tokenAddress, transactionAmount, carolPlatformId, cid, @@ -146,6 +147,7 @@ async function createTransaction( talentLayerEscrow: TalentLayerEscrow, talentLayerService: TalentLayerService, signer: SignerWithAddress, + tokenAddress: string, ): Promise<[ContractTransaction, BigNumber, number, number, number]> { // Create transaction const [ @@ -159,11 +161,16 @@ async function createTransaction( const proposal = await talentLayerService.proposals(serviceId, bobTlId) const value = proposal.rateToken === ethAddress ? totalTransactionAmount : 0 - const tx = await talentLayerEscrow - .connect(signer) - .createTransaction(serviceId, proposalId, metaEvidenceCid, proposal.dataUri, { - value, - }) + let tx: ContractTransaction + tokenAddress === ethAddress + ? (tx = await talentLayerEscrow + .connect(signer) + .createTransaction(serviceId, proposalId, metaEvidenceCid, proposal.dataUri, { + value, + })) + : (tx = await talentLayerEscrow + .connect(signer) + .createTransaction(serviceId, proposalId, metaEvidenceCid, proposal.dataUri)) return [ tx, @@ -223,6 +230,7 @@ describe('Dispute Resolution, standard flow', function () { talentLayerEscrow, talentLayerService, alice, + ethAddress, ) }) @@ -628,7 +636,13 @@ describe('Dispute Resolution, with sender failing to pay arbitration fee on time await deployAndSetup(arbitrationFeeTimeout, ethers.constants.AddressZero) // Create transaction - await createTransaction(talentLayerPlatformID, talentLayerEscrow, talentLayerService, alice) + await createTransaction( + talentLayerPlatformID, + talentLayerEscrow, + talentLayerService, + alice, + ethAddress, + ) // Alice wants to raise a dispute and pays the arbitration fee await talentLayerEscrow.connect(alice).payArbitrationFeeBySender(transactionId, { @@ -700,6 +714,7 @@ describe('Dispute Resolution, with receiver failing to pay arbitration fee on ti talentLayerEscrow, talentLayerService, alice, + ethAddress, ) // Bob wants to raise a dispute and pays the arbitration fee @@ -764,7 +779,13 @@ describe('Dispute Resolution, arbitrator abstaining from giving a ruling', funct // Create transaction ;[, , protocolEscrowFeeRate, originServiceFeeRate, originValidatedProposalFeeRate] = - await createTransaction(talentLayerPlatformID, talentLayerEscrow, talentLayerService, alice) + await createTransaction( + talentLayerPlatformID, + talentLayerEscrow, + talentLayerService, + alice, + ethAddress, + ) // Alice wants to raise a dispute and pays the arbitration fee await talentLayerEscrow.connect(alice).payArbitrationFeeBySender(transactionId, { @@ -868,7 +889,13 @@ describe('Dispute Resolution, receiver winning', function () { await deployAndSetup(arbitrationFeeTimeout, ethers.constants.AddressZero) // Create transaction - await createTransaction(talentLayerPlatformID, talentLayerEscrow, talentLayerService, alice) + await createTransaction( + talentLayerPlatformID, + talentLayerEscrow, + talentLayerService, + alice, + ethAddress, + ) // Bob wants to raise a dispute and pays the arbitration fee and a dispute is created await talentLayerEscrow.connect(bob).payArbitrationFeeByReceiver(transactionId, { @@ -979,7 +1006,13 @@ describe('Dispute Resolution, with ERC20 token transaction', function () { await simpleERC20.connect(alice).approve(talentLayerEscrow.address, totalTransactionAmount) // Create transaction - await createTransaction(talentLayerPlatformID, talentLayerEscrow, talentLayerService, alice) + await createTransaction( + talentLayerPlatformID, + talentLayerEscrow, + talentLayerService, + alice, + simpleERC20, + ) // Alice wants to raise a dispute and pays the arbitration fee await talentLayerEscrow.connect(alice).payArbitrationFeeBySender(transactionId, { From f52e7e5cb2d2aa798db6bd5f25b6a2e1aacf93fb Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Mon, 5 Jun 2023 11:49:43 +0200 Subject: [PATCH 17/99] Added tests for new functions. Signed-off-by: Quentin D.C --- test/batch/fullWorkflow.ts | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index f88c0f66..1ef348a2 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -58,7 +58,7 @@ describe('TalentLayer protocol global testing', function () { chainId: number const nonListedRateToken = '0x6b175474e89094c44da98b954eedeac495271d0f' - const referralAmount = 2 + const referralAmount = 20000 before(async function () { // Get the Signers @@ -837,6 +837,34 @@ describe('TalentLayer protocol global testing', function () { expect(service1Data.ownerId).to.be.equal(aliceTlId) expect(service1Data.dataUri).to.be.equal(cid) expect(service1Data.platformId).to.be.equal(1) + expect(service1Data.referralAmount).to.be.equal(0) + }) + + it('Alice the buyer can create a service with referral', async function () { + const platform = await talentLayerPlatformID.getPlatform(alicePlatformId) + const alicePlatformServicePostingFee = platform.servicePostingFee + + const signature = await getSignatureForService(platformOneOwner, aliceTlId, 5, cid) + await talentLayerService + .connect(alice) + .createServiceWithReferral( + aliceTlId, + alicePlatformId, + cid, + signature, + token.address, + referralAmount, + { + value: alicePlatformServicePostingFee, + }, + ) + const service6Data = await talentLayerService.services(6) + + expect(service6Data.status).to.be.equal(ServiceStatus.Opened) + expect(service6Data.ownerId).to.be.equal(aliceTlId) + expect(service6Data.dataUri).to.be.equal(cid) + expect(service6Data.platformId).to.be.equal(1) + expect(service6Data.referralAmount).to.be.equal(referralAmount) }) it("Alice can't create a new open service with wrong TalentLayer Platform ID", async function () { @@ -854,6 +882,13 @@ describe('TalentLayer protocol global testing', function () { .updateService(aliceTlId, 1, referralAmount, token.address, cid2) const serviceData = await talentLayerService.services(1) expect(serviceData.dataUri).to.be.equal(cid2) + + const newReferralAmount = 40000 + await talentLayerService + .connect(alice) + .updateService(aliceTlId, 6, newReferralAmount, token.address, cid2) + const service6Data = await talentLayerService.services(6) + expect(service6Data.referralAmount).to.be.equal(newReferralAmount) }) it('Alice cannot update her service with a non-whitelisted token', async function () { From 5f4aab57b4345b2b4a1d1846f038d7d96d7ef9cb Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Mon, 5 Jun 2023 12:46:32 +0200 Subject: [PATCH 18/99] Added an event Updated tests Signed-off-by: Quentin D.C --- contracts/Upgrades/TalentLayerServiceV2.sol | 11 ++++++++++- test/batch/fullWorkflow.ts | 5 +++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/contracts/Upgrades/TalentLayerServiceV2.sol b/contracts/Upgrades/TalentLayerServiceV2.sol index 049e8038..02f3f8c4 100644 --- a/contracts/Upgrades/TalentLayerServiceV2.sol +++ b/contracts/Upgrades/TalentLayerServiceV2.sol @@ -131,6 +131,15 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP */ event ServiceDetailedUpdated(uint256 indexed id, string dataUri); + /** + * @notice Emit when data is updated for a Service + * @param id The service ID + * @param dataUri New service Data URI + * @param referralAmount New referral amount + * @param token New service token + */ + event ServiceUpdated(uint256 indexed id, string dataUri, uint256 referralAmount, address token); + /** * @notice Emitted after a new proposal is created * @param serviceId The service id @@ -588,7 +597,7 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP service.referralAmount = _referralAmount; service.token = _token; - emit ServiceDetailedUpdated(_serviceId, _dataUri); + emit ServiceUpdated(_serviceId, _dataUri, _referralAmount, _token); } /** diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index 1ef348a2..00b0fd1a 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -886,9 +886,10 @@ describe('TalentLayer protocol global testing', function () { const newReferralAmount = 40000 await talentLayerService .connect(alice) - .updateService(aliceTlId, 6, newReferralAmount, token.address, cid2) + .updateService(aliceTlId, 6, newReferralAmount, ethers.constants.AddressZero, cid2) const service6Data = await talentLayerService.services(6) expect(service6Data.referralAmount).to.be.equal(newReferralAmount) + expect(service6Data.token).to.be.equal(ethers.constants.AddressZero) }) it('Alice cannot update her service with a non-whitelisted token', async function () { @@ -1430,7 +1431,7 @@ describe('TalentLayer protocol global testing', function () { const alicePlatformProposalPostingFee = platform.proposalPostingFee // Create the service - const serviceId = 6 + const serviceId = 7 const signature = await getSignatureForService(platformOneOwner, aliceTlId, 5, cid) await talentLayerService .connect(alice) From f9a6de8fba63ad5a9670d46d6e83fe0d29d7094d Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Mon, 5 Jun 2023 12:52:11 +0200 Subject: [PATCH 19/99] Updated tests with events emissions Signed-off-by: Quentin D.C --- test/batch/fullWorkflow.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index 00b0fd1a..c0bfd944 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -845,7 +845,7 @@ describe('TalentLayer protocol global testing', function () { const alicePlatformServicePostingFee = platform.servicePostingFee const signature = await getSignatureForService(platformOneOwner, aliceTlId, 5, cid) - await talentLayerService + const tx = await talentLayerService .connect(alice) .createServiceWithReferral( aliceTlId, @@ -860,6 +860,10 @@ describe('TalentLayer protocol global testing', function () { ) const service6Data = await talentLayerService.services(6) + expect(tx) + .to.emit(talentLayerService, 'ServiceCreatedWithReferral') + .withArgs(5, aliceTlId, alicePlatformId, cid, token.address, referralAmount) + expect(service6Data.status).to.be.equal(ServiceStatus.Opened) expect(service6Data.ownerId).to.be.equal(aliceTlId) expect(service6Data.dataUri).to.be.equal(cid) @@ -884,10 +888,14 @@ describe('TalentLayer protocol global testing', function () { expect(serviceData.dataUri).to.be.equal(cid2) const newReferralAmount = 40000 - await talentLayerService + const tx = await talentLayerService .connect(alice) .updateService(aliceTlId, 6, newReferralAmount, ethers.constants.AddressZero, cid2) const service6Data = await talentLayerService.services(6) + + expect(tx) + .to.emit(talentLayerService, 'ServiceUpdated') + .withArgs(6, cid2, newReferralAmount, ethers.constants.AddressZero) expect(service6Data.referralAmount).to.be.equal(newReferralAmount) expect(service6Data.token).to.be.equal(ethers.constants.AddressZero) }) From 14c6fee34791832b2b60f0cb06b60a94404399dd Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Mon, 5 Jun 2023 13:08:44 +0200 Subject: [PATCH 20/99] Added missing assertions + event assertions Added new events tests Signed-off-by: Quentin D.C --- test/batch/fullWorkflow.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index c0bfd944..7bf1a331 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -1003,7 +1003,7 @@ describe('TalentLayer protocol global testing', function () { // Bob creates a proposal on Platform 1 const signature = await getSignatureForProposal(platformOneOwner, bobTlId, 1, cid2) - await talentLayerService + const tx = await talentLayerService .connect(bob) .createProposal(bobTlId, 1, 15, alicePlatformId, cid2, proposalExpirationDate, signature, { value: alicePlatformProposalPostingFee, @@ -1021,8 +1021,13 @@ describe('TalentLayer protocol global testing', function () { expect(proposalDataAfter.rateToken).to.be.equal(ethers.constants.AddressZero) expect(proposalDataAfter.rateAmount.toString()).to.be.equal('15') expect(proposalDataAfter.dataUri).to.be.equal(cid2) + expect(proposalDataAfter.platformId).to.be.equal(alicePlatformId) + expect(proposalDataAfter.expirationDate).to.be.equal(proposalExpirationDate) expect(proposalDataAfter.ownerId).to.be.equal(bobTlId) expect(proposalDataAfter.status.toString()).to.be.equal('0') + expect(tx) + .to.emit(talentLayerService, 'ProposalCreatedWithoutToken') + .withArgs(1, bobTlId, cid2, 'Pending', 15, alicePlatformId, proposalExpirationDate) }) it("Bob can't create another proposal for the same service", async function () { @@ -1082,12 +1087,18 @@ describe('TalentLayer protocol global testing', function () { const proposalDataBefore = await talentLayerService.getProposal(1, bobTlId) expect(proposalDataBefore.rateAmount.toString()).to.be.equal('15') - await talentLayerService + const tx = await talentLayerService .connect(bob) .updateProposal(bobTlId, 1, 18, cid, proposalExpirationDate) const proposalDataAfter = await talentLayerService.getProposal(1, bobTlId) + expect(tx) + .to.emit(talentLayerService, 'ProposalUpdatedWithoutToken') + .withArgs(1, bobTlId, cid, 18, proposalExpirationDate) expect(proposalDataAfter.rateAmount.toString()).to.be.equal('18') + expect(proposalDataAfter.expirationDate).to.be.equal(proposalExpirationDate) + // @dev: This field is deprecated and should always be zero address + expect(proposalDataAfter.rateToken.toString()).to.be.equal(ethers.constants.AddressZero) expect(proposalDataAfter.dataUri).to.be.equal(cid) }) From d8d6f0cb6a93f4de556370d45663c07c95a2ae52 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Mon, 5 Jun 2023 15:29:18 +0200 Subject: [PATCH 21/99] Fixed nat spec Signed-off-by: Quentin D.C --- contracts/Upgrades/TalentLayerServiceV2.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/Upgrades/TalentLayerServiceV2.sol b/contracts/Upgrades/TalentLayerServiceV2.sol index 02f3f8c4..21c6ceaa 100644 --- a/contracts/Upgrades/TalentLayerServiceV2.sol +++ b/contracts/Upgrades/TalentLayerServiceV2.sol @@ -64,8 +64,8 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP * @notice Proposal information struct * @param status the current status of a service * @param ownerId the talentLayerId of the seller - * @param rateToken the token choose for the payment - * @param DEPRECATED - rateAmount the amount of token chosen + * @param DEPRECATED - rateToken the token choose for the payment + * @param rateAmount the amount of token chosen * @param dataUri token Id to IPFS URI mapping * @param expirationDate the timeout for the proposal */ From 68e8c23c1bb6adf19a46717dc04e618b83e7bbc0 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Tue, 6 Jun 2023 08:10:11 +0200 Subject: [PATCH 22/99] Added indexed in event Signed-off-by: Quentin D.C --- contracts/Upgrades/TalentLayerServiceV2.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/Upgrades/TalentLayerServiceV2.sol b/contracts/Upgrades/TalentLayerServiceV2.sol index 21c6ceaa..6a8c368e 100644 --- a/contracts/Upgrades/TalentLayerServiceV2.sol +++ b/contracts/Upgrades/TalentLayerServiceV2.sol @@ -110,7 +110,7 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP * @param referralAmount the amount which the referrer will receive if a proposal is validated by un user which was referred */ event ServiceCreatedWithReferral( - uint256 id, + uint256 indexed id, uint256 ownerId, uint256 platformId, string dataUri, From b37c9c7da7d8d49f7398960d09264c4f049897b7 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Tue, 6 Jun 2023 14:50:48 +0200 Subject: [PATCH 23/99] Refactored Contract upgrades naming & organization Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 12 +- contracts/TalentLayerService.sol | 156 ++++++++++++++--- .../TalentLayerEscrowV1.sol} | 14 +- .../TalentLayerServiceV1.sol} | 158 +++--------------- 4 files changed, 170 insertions(+), 170 deletions(-) rename contracts/{Upgrades/TalentLayerEscrowV2.sol => archive/TalentLayerEscrowV1.sol} (99%) rename contracts/{Upgrades/TalentLayerServiceV2.sol => archive/TalentLayerServiceV1.sol} (80%) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index 77578756..ec65218f 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -469,7 +469,7 @@ contract TalentLayerEscrow is originProposalCreationPlatform.originValidatedProposalFeeRate ); - if (proposal.rateToken == address(0)) { + if (service.token == address(0)) { require(msg.value == transactionAmount, "Non-matching funds"); } else { require(msg.value == 0, "Non-matching funds"); @@ -491,7 +491,7 @@ contract TalentLayerEscrow is id: transactionId, sender: sender, receiver: receiver, - token: proposal.rateToken, + token: service.token, amount: proposal.rateAmount, releasedAmount: 0, serviceId: _serviceId, @@ -513,8 +513,8 @@ contract TalentLayerEscrow is talentLayerServiceContract.afterDeposit(_serviceId, _proposalId, transactionId); - if (proposal.rateToken != address(0)) { - IERC20Upgradeable(proposal.rateToken).safeTransferFrom(sender, address(this), transactionAmount); + if (service.token != address(0)) { + IERC20Upgradeable(service.token).safeTransferFrom(sender, address(this), transactionAmount); } _afterCreateTransaction(service.ownerId, proposal.ownerId, transactionId, _metaEvidence); @@ -844,7 +844,7 @@ contract TalentLayerEscrow is * @notice Emits the events related to the creation of a transaction. * @param _senderId The TL ID of the sender * @param _receiverId The TL ID of the receiver - * @param _transactionId The ID of the transavtion + * @param _transactionId The ID of the transaction * @param _metaEvidence The meta evidence of the transaction */ function _afterCreateTransaction( @@ -947,7 +947,7 @@ contract TalentLayerEscrow is } /** - * @notice Used to validate a realease or a reimburse payment + * @notice Used to validate a release or a reimburse payment * @param _transactionId The transaction linked to the payment * @param _paymentType The type of payment to validate * @param _profileId The profileId of the msgSender diff --git a/contracts/TalentLayerService.sol b/contracts/TalentLayerService.sol index 2252ca1e..c01a5275 100644 --- a/contracts/TalentLayerService.sol +++ b/contracts/TalentLayerService.sol @@ -42,10 +42,12 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @notice Service information struct * @param status the current status of a service * @param ownerId the talentLayerId of the buyer - * @param acceptedProposalId the accepted proposal ID + * @param acceptedProposalId the accepted proposal ID, which is the ID of the user who submitted the proposal * @param dataUri token Id to IPFS URI mapping * @param transactionId the escrow transaction ID linked to the service * @param platformId the platform ID on which the service was created + * @param token the token used for the service's payments, including the referral amount + * @param referralAmount the amount which the referrer will receive if a proposal is validated by un user which was referred */ struct Service { Status status; @@ -54,13 +56,15 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU string dataUri; uint256 transactionId; uint256 platformId; + address token; + uint256 referralAmount; } /** * @notice Proposal information struct * @param status the current status of a service * @param ownerId the talentLayerId of the seller - * @param rateToken the token choose for the payment + * @param DEPRECATED - rateToken the token choose for the payment * @param rateAmount the amount of token chosen * @param dataUri token Id to IPFS URI mapping * @param expirationDate the timeout for the proposal @@ -96,6 +100,24 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU */ event ServiceCreated(uint256 id, uint256 ownerId, uint256 platformId, string dataUri); + /** + * @notice Emitted after a new service is created with referral data + * @param id The service ID (incremental) + * @param ownerId the talentLayerId of the buyer + * @param platformId platform ID on which the Service token was minted + * @param dataUri token Id to IPFS URI mapping + * @param token the token used for the service's payments, including the referral amount + * @param referralAmount the amount which the referrer will receive if a proposal is validated by un user which was referred + */ + event ServiceCreatedWithReferral( + uint256 indexed id, + uint256 ownerId, + uint256 platformId, + string dataUri, + address token, + uint256 referralAmount + ); + /** * @notice Emitted after a service is cancelled by the owner * @param id The service ID @@ -109,6 +131,15 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU */ event ServiceDetailedUpdated(uint256 indexed id, string dataUri); + /** + * @notice Emit when data is updated for a Service + * @param id The service ID + * @param dataUri New service Data URI + * @param referralAmount New referral amount + * @param token New service token + */ + event ServiceUpdated(uint256 indexed id, string dataUri, uint256 referralAmount, address token); + /** * @notice Emitted after a new proposal is created * @param serviceId The service id @@ -131,6 +162,26 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU uint256 expirationDate ); + /** + * @notice Emitted after a new proposal is created + * @param serviceId The service id + * @param ownerId The talentLayerId of the seller who made the proposal + * @param dataUri token Id to IPFS URI mapping + * @param status proposal status + * @param rateAmount the amount of token chosen + * @param platformId the platform ID on which the proposal was created + * @param expirationDate the timeout for the proposal + */ + event ProposalCreatedWithoutToken( + uint256 serviceId, + uint256 ownerId, + string dataUri, + ProposalStatus status, + uint256 rateAmount, + uint256 platformId, + uint256 expirationDate + ); + /** * @notice Emitted after an existing proposal has been updated * @param serviceId The service id @@ -149,6 +200,22 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU uint256 expirationDate ); + /** + * @notice Emitted after an existing proposal has been updated + * @param serviceId The service id + * @param ownerId The talentLayerId of the seller who made the proposal + * @param dataUri token Id to IPFS URI mapping + * @param rateAmount the amount of token chosen + * @param expirationDate the timeout for the proposal + */ + event ProposalUpdatedWithoutToken( + uint256 serviceId, + uint256 ownerId, + string dataUri, + uint256 rateAmount, + uint256 expirationDate + ); + /** * @notice Emitted when the contract owner adds or removes a token from the allowed payment tokens list * @param tokenAddress The address of the payment token @@ -299,14 +366,16 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param _platformId platform ID on which the Service token was created * @param _dataUri IPFS URI of the offchain data of the service * @param _signature optional platform signature to allow the operation + * @param _token token address to be used for the service's payments */ function createService( uint256 _profileId, uint256 _platformId, string calldata _dataUri, - bytes calldata _signature + bytes calldata _signature, + address _token ) public payable onlyOwnerOrDelegate(_profileId) returns (uint256) { - _validateService(_profileId, _platformId, _dataUri, _signature); + _validateService(_profileId, _platformId, _dataUri, _signature, _token); uint256 id = nextServiceId; nextServiceId++; @@ -316,6 +385,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU service.ownerId = _profileId; service.dataUri = _dataUri; service.platformId = _platformId; + service.token = _token; if (serviceNonce[_profileId] == 0 && proposalNonce[_profileId] == 0) { tlId.setHasActivity(_profileId); @@ -327,11 +397,50 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU return id; } + /** + * @notice Allows a buyer to initiate an open service + * @param _profileId The TalentLayer ID of the user owner of the service + * @param _platformId platform ID on which the Service token was created + * @param _dataUri IPFS URI of the offchain data of the service + * @param _signature optional platform signature to allow the operation + * @param _token the token used for the referral amount + * @param _referralAmount the amount which the referrer will receive if a proposal is validated by un user which was referred + */ + function createServiceWithReferral( + uint256 _profileId, + uint256 _platformId, + string calldata _dataUri, + bytes calldata _signature, + address _token, + uint256 _referralAmount + ) public payable onlyOwnerOrDelegate(_profileId) returns (uint256) { + _validateService(_profileId, _platformId, _dataUri, _signature, _token); + + uint256 id = nextServiceId; + nextServiceId++; + + Service storage service = services[id]; + service.status = Status.Opened; + service.ownerId = _profileId; + service.dataUri = _dataUri; + service.platformId = _platformId; + service.token = _token; + service.referralAmount = _referralAmount; + + if (serviceNonce[_profileId] == 0 && proposalNonce[_profileId] == 0) { + tlId.setHasActivity(_profileId); + } + serviceNonce[_profileId]++; + + emit ServiceCreatedWithReferral(id, _profileId, _platformId, _dataUri, _token, _referralAmount); + + return id; + } + /** * @notice Allows an seller to propose his service for a service * @param _profileId The TalentLayer ID of the user owner of the proposal * @param _serviceId The service linked to the new proposal - * @param _rateToken the token choose for the payment * @param _rateAmount the amount of token chosen * @param _dataUri token Id to IPFS URI mapping * @param _platformId platform ID from where the proposal is created @@ -341,19 +450,18 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU function createProposal( uint256 _profileId, uint256 _serviceId, - address _rateToken, uint256 _rateAmount, uint256 _platformId, string calldata _dataUri, uint256 _expirationDate, bytes calldata _signature ) public payable onlyOwnerOrDelegate(_profileId) { - _validateProposal(_profileId, _serviceId, _rateToken, _rateAmount, _platformId, _dataUri, _signature); + _validateProposal(_profileId, _serviceId, _rateAmount, _platformId, _dataUri, _signature); proposals[_serviceId][_profileId] = Proposal({ status: ProposalStatus.Pending, ownerId: _profileId, - rateToken: _rateToken, + rateToken: address(0), rateAmount: _rateAmount, platformId: _platformId, dataUri: _dataUri, @@ -365,12 +473,11 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU } proposalNonce[_profileId]++; - emit ProposalCreated( + emit ProposalCreatedWithoutToken( _serviceId, _profileId, _dataUri, ProposalStatus.Pending, - _rateToken, _rateAmount, _platformId, _expirationDate @@ -381,7 +488,6 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @notice Allows the owner to update his own proposal for a given service * @param _profileId The TalentLayer ID of the user * @param _serviceId The service linked to the new proposal - * @param _rateToken the token choose for the payment * @param _rateAmount the amount of token chosen * @param _dataUri token Id to IPFS URI mapping * @param _expirationDate the time before the proposal is automatically validated @@ -389,27 +495,23 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU function updateProposal( uint256 _profileId, uint256 _serviceId, - address _rateToken, uint256 _rateAmount, string calldata _dataUri, uint256 _expirationDate ) public onlyOwnerOrDelegate(_profileId) { - require(allowedTokenList[_rateToken].isWhitelisted, "Token not allowed"); - Service storage service = services[_serviceId]; Proposal storage proposal = proposals[_serviceId][_profileId]; require(service.status == Status.Opened, "Service not opened"); require(proposal.ownerId == _profileId, "Not the owner"); require(bytes(_dataUri).length == 46, "Invalid cid"); require(proposal.status != ProposalStatus.Validated, "Already validated"); - require(_rateAmount >= allowedTokenList[_rateToken].minimumTransactionAmount, "Amount too low"); + require(_rateAmount >= allowedTokenList[service.token].minimumTransactionAmount, "Amount too low"); - proposal.rateToken = _rateToken; proposal.rateAmount = _rateAmount; proposal.dataUri = _dataUri; proposal.expirationDate = _expirationDate; - emit ProposalUpdated(_serviceId, _profileId, _dataUri, _rateToken, _rateAmount, _expirationDate); + emit ProposalUpdatedWithoutToken(_serviceId, _profileId, _dataUri, _rateAmount, _expirationDate); } /** @@ -474,21 +576,28 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @notice Update Service URI data * @param _profileId The TalentLayer ID of the user, owner of the service * @param _serviceId, Service ID to update + * @param _referralAmount, New referral amount + * @param _token, New token address * @param _dataUri New IPFS URI */ - function updateServiceData( + function updateService( uint256 _profileId, uint256 _serviceId, + uint256 _referralAmount, + address _token, string calldata _dataUri ) public onlyOwnerOrDelegate(_profileId) { Service storage service = services[_serviceId]; require(service.ownerId == _profileId, "Not the owner"); require(service.status == Status.Opened, "status must be opened"); + require(allowedTokenList[_token].isWhitelisted, "Token not allowed"); require(bytes(_dataUri).length == 46, "Invalid cid"); service.dataUri = _dataUri; + service.referralAmount = _referralAmount; + service.token = _token; - emit ServiceDetailedUpdated(_serviceId, _dataUri); + emit ServiceUpdated(_serviceId, _dataUri, _referralAmount, _token); } /** @@ -554,11 +663,13 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU uint256 _profileId, uint256 _platformId, string calldata _dataUri, - bytes calldata _signature + bytes calldata _signature, + address _token ) private view { uint256 servicePostingFee = talentLayerPlatformIdContract.getServicePostingFee(_platformId); require(msg.value == servicePostingFee, "Non-matching funds"); require(bytes(_dataUri).length == 46, "Invalid cid"); + require(allowedTokenList[_token].isWhitelisted, "Token not allowed"); address platformSigner = talentLayerPlatformIdContract.getSigner(_platformId); if (platformSigner != address(0)) { @@ -573,7 +684,6 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @notice Validate a new proposal * @param _profileId The TalentLayer ID of the user * @param _serviceId The service linked to the new proposal - * @param _rateToken the token choose for the payment * @param _rateAmount the amount of token chosen * @param _platformId platform ID on which the Proposal was created * @param _dataUri token Id to IPFS URI mapping @@ -582,18 +692,16 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU function _validateProposal( uint256 _profileId, uint256 _serviceId, - address _rateToken, uint256 _rateAmount, uint256 _platformId, string calldata _dataUri, bytes calldata _signature ) private view { - require(allowedTokenList[_rateToken].isWhitelisted, "Token not allowed"); uint256 proposalPostingFee = talentLayerPlatformIdContract.getProposalPostingFee(_platformId); require(msg.value == proposalPostingFee, "Non-matching funds"); - require(_rateAmount >= allowedTokenList[_rateToken].minimumTransactionAmount, "Amount too low"); Service storage service = services[_serviceId]; + require(_rateAmount >= allowedTokenList[service.token].minimumTransactionAmount, "Amount too low"); require(service.status == Status.Opened, "Service not opened"); require(service.ownerId != 0, "Service not exist"); require(proposals[_serviceId][_profileId].ownerId != _profileId, "proposal already exist"); diff --git a/contracts/Upgrades/TalentLayerEscrowV2.sol b/contracts/archive/TalentLayerEscrowV1.sol similarity index 99% rename from contracts/Upgrades/TalentLayerEscrowV2.sol rename to contracts/archive/TalentLayerEscrowV1.sol index 6c037ed9..fdf3faf4 100644 --- a/contracts/Upgrades/TalentLayerEscrowV2.sol +++ b/contracts/archive/TalentLayerEscrowV1.sol @@ -18,7 +18,7 @@ import {Arbitrator} from "../Arbitrator.sol"; * @title TalentLayer Escrow Contract * @author TalentLayer Team | Website: https://talentlayer.org | Twitter: @talentlayer */ -contract TalentLayerEscrowV2 is +contract TalentLayerEscrowV1 is Initializable, ERC2771RecipientUpgradeable, PausableUpgradeable, @@ -469,7 +469,7 @@ contract TalentLayerEscrowV2 is originProposalCreationPlatform.originValidatedProposalFeeRate ); - if (service.token == address(0)) { + if (proposal.rateToken == address(0)) { require(msg.value == transactionAmount, "Non-matching funds"); } else { require(msg.value == 0, "Non-matching funds"); @@ -491,7 +491,7 @@ contract TalentLayerEscrowV2 is id: transactionId, sender: sender, receiver: receiver, - token: service.token, + token: proposal.rateToken, amount: proposal.rateAmount, releasedAmount: 0, serviceId: _serviceId, @@ -513,8 +513,8 @@ contract TalentLayerEscrowV2 is talentLayerServiceContract.afterDeposit(_serviceId, _proposalId, transactionId); - if (service.token != address(0)) { - IERC20Upgradeable(service.token).safeTransferFrom(sender, address(this), transactionAmount); + if (proposal.rateToken != address(0)) { + IERC20Upgradeable(proposal.rateToken).safeTransferFrom(sender, address(this), transactionAmount); } _afterCreateTransaction(service.ownerId, proposal.ownerId, transactionId, _metaEvidence); @@ -844,7 +844,7 @@ contract TalentLayerEscrowV2 is * @notice Emits the events related to the creation of a transaction. * @param _senderId The TL ID of the sender * @param _receiverId The TL ID of the receiver - * @param _transactionId The ID of the transaction + * @param _transactionId The ID of the transavtion * @param _metaEvidence The meta evidence of the transaction */ function _afterCreateTransaction( @@ -947,7 +947,7 @@ contract TalentLayerEscrowV2 is } /** - * @notice Used to validate a release or a reimburse payment + * @notice Used to validate a realease or a reimburse payment * @param _transactionId The transaction linked to the payment * @param _paymentType The type of payment to validate * @param _profileId The profileId of the msgSender diff --git a/contracts/Upgrades/TalentLayerServiceV2.sol b/contracts/archive/TalentLayerServiceV1.sol similarity index 80% rename from contracts/Upgrades/TalentLayerServiceV2.sol rename to contracts/archive/TalentLayerServiceV1.sol index 6a8c368e..4ad632be 100644 --- a/contracts/Upgrades/TalentLayerServiceV2.sol +++ b/contracts/archive/TalentLayerServiceV1.sol @@ -14,7 +14,7 @@ import {ECDSAUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/crypto * @title TalentLayerService Contract * @author TalentLayer Team | Website: https://talentlayer.org | Twitter: @talentlayer */ -contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUPSUpgradeable, AccessControlUpgradeable { +contract TalentLayerServiceV1 is Initializable, ERC2771RecipientUpgradeable, UUPSUpgradeable, AccessControlUpgradeable { // =========================== Enum ============================== /** @@ -42,12 +42,10 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP * @notice Service information struct * @param status the current status of a service * @param ownerId the talentLayerId of the buyer - * @param acceptedProposalId the accepted proposal ID, which is the ID of the user who submitted the proposal + * @param acceptedProposalId the accepted proposal ID * @param dataUri token Id to IPFS URI mapping * @param transactionId the escrow transaction ID linked to the service * @param platformId the platform ID on which the service was created - * @param token the token used for the service's payments, including the referral amount - * @param referralAmount the amount which the referrer will receive if a proposal is validated by un user which was referred */ struct Service { Status status; @@ -56,15 +54,13 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP string dataUri; uint256 transactionId; uint256 platformId; - address token; - uint256 referralAmount; } /** * @notice Proposal information struct * @param status the current status of a service * @param ownerId the talentLayerId of the seller - * @param DEPRECATED - rateToken the token choose for the payment + * @param rateToken the token choose for the payment * @param rateAmount the amount of token chosen * @param dataUri token Id to IPFS URI mapping * @param expirationDate the timeout for the proposal @@ -100,24 +96,6 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP */ event ServiceCreated(uint256 id, uint256 ownerId, uint256 platformId, string dataUri); - /** - * @notice Emitted after a new service is created with referral data - * @param id The service ID (incremental) - * @param ownerId the talentLayerId of the buyer - * @param platformId platform ID on which the Service token was minted - * @param dataUri token Id to IPFS URI mapping - * @param token the token used for the service's payments, including the referral amount - * @param referralAmount the amount which the referrer will receive if a proposal is validated by un user which was referred - */ - event ServiceCreatedWithReferral( - uint256 indexed id, - uint256 ownerId, - uint256 platformId, - string dataUri, - address token, - uint256 referralAmount - ); - /** * @notice Emitted after a service is cancelled by the owner * @param id The service ID @@ -131,15 +109,6 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP */ event ServiceDetailedUpdated(uint256 indexed id, string dataUri); - /** - * @notice Emit when data is updated for a Service - * @param id The service ID - * @param dataUri New service Data URI - * @param referralAmount New referral amount - * @param token New service token - */ - event ServiceUpdated(uint256 indexed id, string dataUri, uint256 referralAmount, address token); - /** * @notice Emitted after a new proposal is created * @param serviceId The service id @@ -162,26 +131,6 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP uint256 expirationDate ); - /** - * @notice Emitted after a new proposal is created - * @param serviceId The service id - * @param ownerId The talentLayerId of the seller who made the proposal - * @param dataUri token Id to IPFS URI mapping - * @param status proposal status - * @param rateAmount the amount of token chosen - * @param platformId the platform ID on which the proposal was created - * @param expirationDate the timeout for the proposal - */ - event ProposalCreatedWithoutToken( - uint256 serviceId, - uint256 ownerId, - string dataUri, - ProposalStatus status, - uint256 rateAmount, - uint256 platformId, - uint256 expirationDate - ); - /** * @notice Emitted after an existing proposal has been updated * @param serviceId The service id @@ -200,22 +149,6 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP uint256 expirationDate ); - /** - * @notice Emitted after an existing proposal has been updated - * @param serviceId The service id - * @param ownerId The talentLayerId of the seller who made the proposal - * @param dataUri token Id to IPFS URI mapping - * @param rateAmount the amount of token chosen - * @param expirationDate the timeout for the proposal - */ - event ProposalUpdatedWithoutToken( - uint256 serviceId, - uint256 ownerId, - string dataUri, - uint256 rateAmount, - uint256 expirationDate - ); - /** * @notice Emitted when the contract owner adds or removes a token from the allowed payment tokens list * @param tokenAddress The address of the payment token @@ -366,16 +299,14 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP * @param _platformId platform ID on which the Service token was created * @param _dataUri IPFS URI of the offchain data of the service * @param _signature optional platform signature to allow the operation - * @param _token token address to be used for the service's payments */ function createService( uint256 _profileId, uint256 _platformId, string calldata _dataUri, - bytes calldata _signature, - address _token + bytes calldata _signature ) public payable onlyOwnerOrDelegate(_profileId) returns (uint256) { - _validateService(_profileId, _platformId, _dataUri, _signature, _token); + _validateService(_profileId, _platformId, _dataUri, _signature); uint256 id = nextServiceId; nextServiceId++; @@ -385,7 +316,6 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP service.ownerId = _profileId; service.dataUri = _dataUri; service.platformId = _platformId; - service.token = _token; if (serviceNonce[_profileId] == 0 && proposalNonce[_profileId] == 0) { tlId.setHasActivity(_profileId); @@ -397,50 +327,11 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP return id; } - /** - * @notice Allows a buyer to initiate an open service - * @param _profileId The TalentLayer ID of the user owner of the service - * @param _platformId platform ID on which the Service token was created - * @param _dataUri IPFS URI of the offchain data of the service - * @param _signature optional platform signature to allow the operation - * @param _token the token used for the referral amount - * @param _referralAmount the amount which the referrer will receive if a proposal is validated by un user which was referred - */ - function createServiceWithReferral( - uint256 _profileId, - uint256 _platformId, - string calldata _dataUri, - bytes calldata _signature, - address _token, - uint256 _referralAmount - ) public payable onlyOwnerOrDelegate(_profileId) returns (uint256) { - _validateService(_profileId, _platformId, _dataUri, _signature, _token); - - uint256 id = nextServiceId; - nextServiceId++; - - Service storage service = services[id]; - service.status = Status.Opened; - service.ownerId = _profileId; - service.dataUri = _dataUri; - service.platformId = _platformId; - service.token = _token; - service.referralAmount = _referralAmount; - - if (serviceNonce[_profileId] == 0 && proposalNonce[_profileId] == 0) { - tlId.setHasActivity(_profileId); - } - serviceNonce[_profileId]++; - - emit ServiceCreatedWithReferral(id, _profileId, _platformId, _dataUri, _token, _referralAmount); - - return id; - } - /** * @notice Allows an seller to propose his service for a service * @param _profileId The TalentLayer ID of the user owner of the proposal * @param _serviceId The service linked to the new proposal + * @param _rateToken the token choose for the payment * @param _rateAmount the amount of token chosen * @param _dataUri token Id to IPFS URI mapping * @param _platformId platform ID from where the proposal is created @@ -450,18 +341,19 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP function createProposal( uint256 _profileId, uint256 _serviceId, + address _rateToken, uint256 _rateAmount, uint256 _platformId, string calldata _dataUri, uint256 _expirationDate, bytes calldata _signature ) public payable onlyOwnerOrDelegate(_profileId) { - _validateProposal(_profileId, _serviceId, _rateAmount, _platformId, _dataUri, _signature); + _validateProposal(_profileId, _serviceId, _rateToken, _rateAmount, _platformId, _dataUri, _signature); proposals[_serviceId][_profileId] = Proposal({ status: ProposalStatus.Pending, ownerId: _profileId, - rateToken: address(0), + rateToken: _rateToken, rateAmount: _rateAmount, platformId: _platformId, dataUri: _dataUri, @@ -473,11 +365,12 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP } proposalNonce[_profileId]++; - emit ProposalCreatedWithoutToken( + emit ProposalCreated( _serviceId, _profileId, _dataUri, ProposalStatus.Pending, + _rateToken, _rateAmount, _platformId, _expirationDate @@ -488,6 +381,7 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP * @notice Allows the owner to update his own proposal for a given service * @param _profileId The TalentLayer ID of the user * @param _serviceId The service linked to the new proposal + * @param _rateToken the token choose for the payment * @param _rateAmount the amount of token chosen * @param _dataUri token Id to IPFS URI mapping * @param _expirationDate the time before the proposal is automatically validated @@ -495,23 +389,27 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP function updateProposal( uint256 _profileId, uint256 _serviceId, + address _rateToken, uint256 _rateAmount, string calldata _dataUri, uint256 _expirationDate ) public onlyOwnerOrDelegate(_profileId) { + require(allowedTokenList[_rateToken].isWhitelisted, "Token not allowed"); + Service storage service = services[_serviceId]; Proposal storage proposal = proposals[_serviceId][_profileId]; require(service.status == Status.Opened, "Service not opened"); require(proposal.ownerId == _profileId, "Not the owner"); require(bytes(_dataUri).length == 46, "Invalid cid"); require(proposal.status != ProposalStatus.Validated, "Already validated"); - require(_rateAmount >= allowedTokenList[service.token].minimumTransactionAmount, "Amount too low"); + require(_rateAmount >= allowedTokenList[_rateToken].minimumTransactionAmount, "Amount too low"); + proposal.rateToken = _rateToken; proposal.rateAmount = _rateAmount; proposal.dataUri = _dataUri; proposal.expirationDate = _expirationDate; - emit ProposalUpdatedWithoutToken(_serviceId, _profileId, _dataUri, _rateAmount, _expirationDate); + emit ProposalUpdated(_serviceId, _profileId, _dataUri, _rateToken, _rateAmount, _expirationDate); } /** @@ -576,28 +474,21 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP * @notice Update Service URI data * @param _profileId The TalentLayer ID of the user, owner of the service * @param _serviceId, Service ID to update - * @param _referralAmount, New referral amount - * @param _token, New token address * @param _dataUri New IPFS URI */ - function updateService( + function updateServiceData( uint256 _profileId, uint256 _serviceId, - uint256 _referralAmount, - address _token, string calldata _dataUri ) public onlyOwnerOrDelegate(_profileId) { Service storage service = services[_serviceId]; require(service.ownerId == _profileId, "Not the owner"); require(service.status == Status.Opened, "status must be opened"); - require(allowedTokenList[_token].isWhitelisted, "Token not allowed"); require(bytes(_dataUri).length == 46, "Invalid cid"); service.dataUri = _dataUri; - service.referralAmount = _referralAmount; - service.token = _token; - emit ServiceUpdated(_serviceId, _dataUri, _referralAmount, _token); + emit ServiceDetailedUpdated(_serviceId, _dataUri); } /** @@ -663,13 +554,11 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP uint256 _profileId, uint256 _platformId, string calldata _dataUri, - bytes calldata _signature, - address _token + bytes calldata _signature ) private view { uint256 servicePostingFee = talentLayerPlatformIdContract.getServicePostingFee(_platformId); require(msg.value == servicePostingFee, "Non-matching funds"); require(bytes(_dataUri).length == 46, "Invalid cid"); - require(allowedTokenList[_token].isWhitelisted, "Token not allowed"); address platformSigner = talentLayerPlatformIdContract.getSigner(_platformId); if (platformSigner != address(0)) { @@ -684,6 +573,7 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP * @notice Validate a new proposal * @param _profileId The TalentLayer ID of the user * @param _serviceId The service linked to the new proposal + * @param _rateToken the token choose for the payment * @param _rateAmount the amount of token chosen * @param _platformId platform ID on which the Proposal was created * @param _dataUri token Id to IPFS URI mapping @@ -692,16 +582,18 @@ contract TalentLayerServiceV2 is Initializable, ERC2771RecipientUpgradeable, UUP function _validateProposal( uint256 _profileId, uint256 _serviceId, + address _rateToken, uint256 _rateAmount, uint256 _platformId, string calldata _dataUri, bytes calldata _signature ) private view { + require(allowedTokenList[_rateToken].isWhitelisted, "Token not allowed"); uint256 proposalPostingFee = talentLayerPlatformIdContract.getProposalPostingFee(_platformId); require(msg.value == proposalPostingFee, "Non-matching funds"); + require(_rateAmount >= allowedTokenList[_rateToken].minimumTransactionAmount, "Amount too low"); Service storage service = services[_serviceId]; - require(_rateAmount >= allowedTokenList[service.token].minimumTransactionAmount, "Amount too low"); require(service.status == Status.Opened, "Service not opened"); require(service.ownerId != 0, "Service not exist"); require(proposals[_serviceId][_profileId].ownerId != _profileId, "proposal already exist"); From 6ca051f2f077ad539f7cfb3805af4d1340daf86e Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Tue, 6 Jun 2023 14:51:29 +0200 Subject: [PATCH 24/99] Refactored tests to fit new naming Signed-off-by: Quentin D.C --- test/batch/delegationSystem.ts | 2 +- test/batch/disputeResolution.ts | 4 ++-- test/batch/fullWorkflow.ts | 2 +- test/batch/pausableEscrow.ts | 2 +- test/batch/platformVerification.ts | 2 +- test/batch/serviceCompletion.ts | 2 +- test/batch/transferProfileIds.ts | 5 +++-- test/manual/audit.ts | 15 +++------------ test/manual/loadTest.ts | 11 ++++++++--- test/utils/deploy.ts | 10 +++++----- 10 files changed, 26 insertions(+), 29 deletions(-) diff --git a/test/batch/delegationSystem.ts b/test/batch/delegationSystem.ts index 67b011ce..54378257 100644 --- a/test/batch/delegationSystem.ts +++ b/test/batch/delegationSystem.ts @@ -44,7 +44,7 @@ async function deployAndSetup( , talentLayerService, talentLayerReview, - ] = await deploy(true) + ] = await deploy(false) // Deployer whitelists a list of authorized tokens await talentLayerService diff --git a/test/batch/disputeResolution.ts b/test/batch/disputeResolution.ts index 201cd5d1..dba303c0 100644 --- a/test/batch/disputeResolution.ts +++ b/test/batch/disputeResolution.ts @@ -56,7 +56,7 @@ async function deployAndSetup( talentLayerEscrow, talentLayerArbitrator, talentLayerService, - ] = await deploy(true) + ] = await deploy(false) // Deployer whitelists a list of authorized tokens await talentLayerService @@ -1011,7 +1011,7 @@ describe('Dispute Resolution, with ERC20 token transaction', function () { talentLayerEscrow, talentLayerService, alice, - simpleERC20, + simpleERC20.address, ) // Alice wants to raise a dispute and pays the arbitration fee diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index 7bf1a331..eac73714 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -71,7 +71,7 @@ describe('TalentLayer protocol global testing', function () { talentLayerService, talentLayerReview, token, - ] = await deploy(true) + ] = await deploy(false) // Grant Platform Id Mint role to Deployer and Bob const mintRole = await talentLayerPlatformID.MINT_ROLE() diff --git a/test/batch/pausableEscrow.ts b/test/batch/pausableEscrow.ts index b487f592..fe69e540 100644 --- a/test/batch/pausableEscrow.ts +++ b/test/batch/pausableEscrow.ts @@ -40,7 +40,7 @@ async function deployAndSetup(): Promise< , talentLayerService, talentLayerReview, - ] = await deploy(true) + ] = await deploy(false) // Grant Platform Id Mint role to Deployer and Bob const mintRole = await talentLayerPlatformID.MINT_ROLE() diff --git a/test/batch/platformVerification.ts b/test/batch/platformVerification.ts index cb343cb0..c07a3c89 100644 --- a/test/batch/platformVerification.ts +++ b/test/batch/platformVerification.ts @@ -44,7 +44,7 @@ async function deployAndSetup(): Promise< talentLayerService, talentLayerReview, simpleERC20, - ] = await deploy(true) + ] = await deploy(false) // Deployer mints Platform Id for Carol const platformName = 'hirevibes' diff --git a/test/batch/serviceCompletion.ts b/test/batch/serviceCompletion.ts index d8bca8c4..2b4823c1 100644 --- a/test/batch/serviceCompletion.ts +++ b/test/batch/serviceCompletion.ts @@ -41,7 +41,7 @@ async function deployAndSetup(): Promise< , talentLayerService, talentLayerReview, - ] = await deploy(true) + ] = await deploy(false) // Grant Platform Id Mint role to Deployer and Bob const mintRole = await talentLayerPlatformID.MINT_ROLE() diff --git a/test/batch/transferProfileIds.ts b/test/batch/transferProfileIds.ts index fe6f9288..19677893 100644 --- a/test/batch/transferProfileIds.ts +++ b/test/batch/transferProfileIds.ts @@ -92,7 +92,9 @@ describe('Transfer of TalentLayer IDs', function () { // Bob creates a new service const signature = await getSignatureForService(eve, bobTlId.toNumber(), 0, cid) - await talentLayerService.connect(bob).createService(bobTlId, evePlatformId, cid, signature) + await talentLayerService + .connect(bob) + .createService(bobTlId, evePlatformId, cid, signature, tokenAddress) expect(await talentLayerID.hasActivity(bobTlId)).to.be.true @@ -124,7 +126,6 @@ describe('Transfer of TalentLayer IDs', function () { .createProposal( carolTlId, serviceId, - tokenAddress, transactionAmount, evePlatformId, cid, diff --git a/test/manual/audit.ts b/test/manual/audit.ts index 5eddb596..1b9572d1 100644 --- a/test/manual/audit.ts +++ b/test/manual/audit.ts @@ -42,7 +42,7 @@ async function deployAndSetup(): Promise< talentLayerService, talentLayerReview, simpleERC20, - ] = await deploy(true) + ] = await deploy(false) // Deployer mints Platform Id for Carol const platformName = 'hirevibes' @@ -117,7 +117,7 @@ describe('Audit test', function () { const signature = await getSignatureForService(carol, aliceTlId.toNumber(), 0, cid) await talentLayerService .connect(alice) - .createService(aliceTlId, carolPlatformId, cid, signature, { + .createService(aliceTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero, { value: 0, }) @@ -125,16 +125,7 @@ describe('Audit test', function () { const signature2 = await getSignatureForProposal(carol, bobTlId.toNumber(), 0, cid) const tx = talentLayerService .connect(bob) - .createProposal( - bobTlId, - 99, - ethers.constants.AddressZero, - 1000, - carolPlatformId, - cid, - proposalExpirationDate, - signature2, - ) + .createProposal(bobTlId, 99, 1000, carolPlatformId, cid, proposalExpirationDate, signature2) await expect(tx).to.revertedWith('Service not exist') }) }) diff --git a/test/manual/loadTest.ts b/test/manual/loadTest.ts index 2d23583d..2eea263d 100644 --- a/test/manual/loadTest.ts +++ b/test/manual/loadTest.ts @@ -50,7 +50,7 @@ describe('Load test', function () { talentLayerEscrow, talentLayerArbitrator, talentLayerService, - ] = await deploy(true) + ] = await deploy(false) // Grant Platform Id Mint role to Alice const mintRole = await talentLayerPlatformID.MINT_ROLE() @@ -91,7 +91,13 @@ describe('Load test', function () { await expect( await talentLayerService .connect(signers[signerIndex]) - .createService(talentLayerId, platformId, cid, signature), + .createService( + talentLayerId, + platformId, + cid, + signature, + ethers.constants.AddressZero, + ), ).to.emit(talentLayerService, 'ServiceCreated') } } @@ -123,7 +129,6 @@ describe('Load test', function () { .createProposal( talentLayerId, serviceId, - ethers.constants.AddressZero, VALUE, platformId, cid, diff --git a/test/utils/deploy.ts b/test/utils/deploy.ts index bcbf7077..05f2308d 100644 --- a/test/utils/deploy.ts +++ b/test/utils/deploy.ts @@ -37,12 +37,12 @@ export async function deploy( // Deploy TalentLayerID const TalentLayerID = await ethers.getContractFactory('TalentLayerID') const talentLayerIDArgs: [string] = [talentLayerPlatformID.address] - const talentLayerID = await upgrades.deployProxy(TalentLayerID, talentLayerIDArgs) + let talentLayerID = await upgrades.deployProxy(TalentLayerID, talentLayerIDArgs) - // if (applyUpgrade) { - // const TalentLayerIDV2 = await ethers.getContractFactory('TalentLayerIDV2') - // talentLayerID = await upgrades.upgradeProxy(talentLayerID.address, TalentLayerIDV2) - // } + if (applyUpgrade) { + const TalentLayerIDV2 = await ethers.getContractFactory('TalentLayerIDV2') + talentLayerID = await upgrades.upgradeProxy(talentLayerID.address, TalentLayerIDV2) + } // Deploy TalentLayerService const TalentLayerService = await ethers.getContractFactory('TalentLayerService') From e02ba9d8e84c0ab9960caf97d8b0b535c77449db Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Thu, 8 Jun 2023 07:43:17 +0200 Subject: [PATCH 25/99] Added new function to TalentLayerService.sol contract Signed-off-by: Quentin D.C --- contracts/TalentLayerService.sol | 74 +++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 6 deletions(-) diff --git a/contracts/TalentLayerService.sol b/contracts/TalentLayerService.sol index c01a5275..4c67dbbc 100644 --- a/contracts/TalentLayerService.sol +++ b/contracts/TalentLayerService.sol @@ -68,6 +68,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param rateAmount the amount of token chosen * @param dataUri token Id to IPFS URI mapping * @param expirationDate the timeout for the proposal + * @param referrer the id of the referrer (Zero if no referrer) */ struct Proposal { ProposalStatus status; @@ -77,6 +78,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU uint256 platformId; string dataUri; uint256 expirationDate; + uint256 referrer; } /** @@ -171,6 +173,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param rateAmount the amount of token chosen * @param platformId the platform ID on which the proposal was created * @param expirationDate the timeout for the proposal + * @param referrerId the id of the referrer (Zero if no referrer) */ event ProposalCreatedWithoutToken( uint256 serviceId, @@ -179,7 +182,8 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU ProposalStatus status, uint256 rateAmount, uint256 platformId, - uint256 expirationDate + uint256 expirationDate, + uint256 referrerId ); /** @@ -207,13 +211,15 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param dataUri token Id to IPFS URI mapping * @param rateAmount the amount of token chosen * @param expirationDate the timeout for the proposal + * @param referrerId the id of the referrer (Zero if no referrer) */ event ProposalUpdatedWithoutToken( uint256 serviceId, uint256 ownerId, string dataUri, uint256 rateAmount, - uint256 expirationDate + uint256 expirationDate, + uint256 referrerId ); /** @@ -465,7 +471,8 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU rateAmount: _rateAmount, platformId: _platformId, dataUri: _dataUri, - expirationDate: _expirationDate + expirationDate: _expirationDate, + referrer: 0 }); if (serviceNonce[_profileId] == 0 && proposalNonce[_profileId] == 0) { @@ -480,7 +487,59 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU ProposalStatus.Pending, _rateAmount, _platformId, - _expirationDate + _expirationDate, + 0 + ); + } + + /** + * @notice Allows an seller to propose his service for a service + * @param _profileId The TalentLayer ID of the user owner of the proposal + * @param _serviceId The service linked to the new proposal + * @param _rateAmount the amount of token chosen + * @param _dataUri token Id to IPFS URI mapping + * @param _platformId platform ID from where the proposal is created + * @param _expirationDate the time before the proposal is automatically validated + * @param _signature optional platform signature to allow the operation + * @param _referrerId the id of the referrer (Zero if no referrer) + */ + function createProposalWithReferrer( + uint256 _profileId, + uint256 _serviceId, + uint256 _rateAmount, + uint256 _platformId, + string calldata _dataUri, + uint256 _expirationDate, + bytes calldata _signature, + uint256 _referrerId + ) public payable onlyOwnerOrDelegate(_profileId) { + _validateProposal(_profileId, _serviceId, _rateAmount, _platformId, _dataUri, _signature); + + proposals[_serviceId][_profileId] = Proposal({ + status: ProposalStatus.Pending, + ownerId: _profileId, + rateToken: address(0), + rateAmount: _rateAmount, + platformId: _platformId, + dataUri: _dataUri, + expirationDate: _expirationDate, + referrer: _referrerId + }); + + if (serviceNonce[_profileId] == 0 && proposalNonce[_profileId] == 0) { + tlId.setHasActivity(_profileId); + } + proposalNonce[_profileId]++; + + emit ProposalCreatedWithoutToken( + _serviceId, + _profileId, + _dataUri, + ProposalStatus.Pending, + _rateAmount, + _platformId, + _expirationDate, + _referrerId ); } @@ -491,13 +550,15 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param _rateAmount the amount of token chosen * @param _dataUri token Id to IPFS URI mapping * @param _expirationDate the time before the proposal is automatically validated + * @param _referrerId the id of the referrer (Zero if no referrer) */ function updateProposal( uint256 _profileId, uint256 _serviceId, uint256 _rateAmount, string calldata _dataUri, - uint256 _expirationDate + uint256 _expirationDate, + uint256 _referrerId ) public onlyOwnerOrDelegate(_profileId) { Service storage service = services[_serviceId]; Proposal storage proposal = proposals[_serviceId][_profileId]; @@ -510,8 +571,9 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU proposal.rateAmount = _rateAmount; proposal.dataUri = _dataUri; proposal.expirationDate = _expirationDate; + proposal.referrer = _referrerId; - emit ProposalUpdatedWithoutToken(_serviceId, _profileId, _dataUri, _rateAmount, _expirationDate); + emit ProposalUpdatedWithoutToken(_serviceId, _profileId, _dataUri, _rateAmount, _expirationDate, _referrerId); } /** From 6133da95c2badb2e8392480d9e986c84f2c2903a Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Thu, 8 Jun 2023 07:47:49 +0200 Subject: [PATCH 26/99] Updated tests Signed-off-by: Quentin D.C --- test/batch/delegationSystem.ts | 9 ++++++++- test/batch/fullWorkflow.ts | 18 ++++++++++++------ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/test/batch/delegationSystem.ts b/test/batch/delegationSystem.ts index 54378257..47c995e8 100644 --- a/test/batch/delegationSystem.ts +++ b/test/batch/delegationSystem.ts @@ -170,7 +170,14 @@ describe('Delegation System', function () { it('Eve can update a proposal on behalf of Bob', async function () { const tx = await talentLayerService .connect(eve) - .updateProposal(bobTlId, serviceId, transactionAmount, cid, proposalExpirationDate) + .updateProposal( + bobTlId, + serviceId, + transactionAmount, + cid, + proposalExpirationDate, + aliceTlId, + ) await expect(tx).to.not.be.reverted }) diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index eac73714..e3c9ea27 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -954,14 +954,13 @@ describe('TalentLayer protocol global testing', function () { it('Bob cannot update his proposal since it does not exist yet', async function () { const tx = talentLayerService .connect(bob) - .updateProposal(bobTlId, 1, 18, cid, proposalExpirationDate) + .updateProposal(bobTlId, 1, 18, cid, proposalExpirationDate, aliceTlId) await expect(tx).to.be.revertedWith('Not the owner') }) it('Bob can t create a proposal with an amount under the transcation limit amount ', async function () { // Proposal on the Open service n 1 - const rateToken = '0xC01FcDfDE3B2ABA1eab76731493C617FfAED2F10' const platform = await talentLayerPlatformID.getPlatform(alicePlatformId) const alicePlatformProposalPostingFee = platform.servicePostingFee @@ -1089,7 +1088,7 @@ describe('TalentLayer protocol global testing', function () { const tx = await talentLayerService .connect(bob) - .updateProposal(bobTlId, 1, 18, cid, proposalExpirationDate) + .updateProposal(bobTlId, 1, 18, cid, proposalExpirationDate, aliceTlId) const proposalDataAfter = await talentLayerService.getProposal(1, bobTlId) expect(tx) @@ -1109,7 +1108,14 @@ describe('TalentLayer protocol global testing', function () { const tx = talentLayerService .connect(bob) - .updateProposal(bobTlId, 1, minTransactionAmount.sub(1), cid, proposalExpirationDate) + .updateProposal( + bobTlId, + 1, + minTransactionAmount.sub(1), + cid, + proposalExpirationDate, + aliceTlId, + ) await expect(tx).to.be.revertedWith('Amount too low') }) @@ -1305,7 +1311,7 @@ describe('TalentLayer protocol global testing', function () { it('Bob cannot update his proposal after the service is confirmed', async function () { const tx = talentLayerService .connect(bob) - .updateProposal(bobTlId, serviceId, 18, cid, proposalExpirationDate) + .updateProposal(bobTlId, serviceId, 18, cid, proposalExpirationDate, aliceTlId) await expect(tx).to.be.revertedWith('Service not opened') }) @@ -1669,7 +1675,7 @@ describe('TalentLayer protocol global testing', function () { it('Bob will try to front run the proposal validation by changing the proposal dataUri.', async function () { await talentLayerService .connect(bob) - .updateProposal(bobTlId, serviceId, amountBob, cid2, proposalExpirationDate) + .updateProposal(bobTlId, serviceId, amountBob, cid2, proposalExpirationDate, aliceTlId) await expect( talentLayerEscrow From cc3e7ed0dd59525291a483f41f4baab4666102f1 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Thu, 8 Jun 2023 07:56:45 +0200 Subject: [PATCH 27/99] Renamed contract variable Added test assertion Signed-off-by: Quentin D.C --- contracts/TalentLayerService.sol | 10 +++++----- test/batch/fullWorkflow.ts | 6 ++++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/contracts/TalentLayerService.sol b/contracts/TalentLayerService.sol index 4c67dbbc..77deac0f 100644 --- a/contracts/TalentLayerService.sol +++ b/contracts/TalentLayerService.sol @@ -68,7 +68,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param rateAmount the amount of token chosen * @param dataUri token Id to IPFS URI mapping * @param expirationDate the timeout for the proposal - * @param referrer the id of the referrer (Zero if no referrer) + * @param referrerId the id of the referrer (Zero if no referrer) */ struct Proposal { ProposalStatus status; @@ -78,7 +78,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU uint256 platformId; string dataUri; uint256 expirationDate; - uint256 referrer; + uint256 referrerId; } /** @@ -472,7 +472,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU platformId: _platformId, dataUri: _dataUri, expirationDate: _expirationDate, - referrer: 0 + referrerId: 0 }); if (serviceNonce[_profileId] == 0 && proposalNonce[_profileId] == 0) { @@ -523,7 +523,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU platformId: _platformId, dataUri: _dataUri, expirationDate: _expirationDate, - referrer: _referrerId + referrerId: _referrerId }); if (serviceNonce[_profileId] == 0 && proposalNonce[_profileId] == 0) { @@ -571,7 +571,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU proposal.rateAmount = _rateAmount; proposal.dataUri = _dataUri; proposal.expirationDate = _expirationDate; - proposal.referrer = _referrerId; + proposal.referrerId = _referrerId; emit ProposalUpdatedWithoutToken(_serviceId, _profileId, _dataUri, _rateAmount, _expirationDate, _referrerId); } diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index e3c9ea27..161ce118 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -959,7 +959,7 @@ describe('TalentLayer protocol global testing', function () { await expect(tx).to.be.revertedWith('Not the owner') }) - it('Bob can t create a proposal with an amount under the transcation limit amount ', async function () { + it('Bob can t create a proposal with an amount under the transaction limit amount ', async function () { // Proposal on the Open service n 1 const platform = await talentLayerPlatformID.getPlatform(alicePlatformId) const alicePlatformProposalPostingFee = platform.servicePostingFee @@ -1024,9 +1024,10 @@ describe('TalentLayer protocol global testing', function () { expect(proposalDataAfter.expirationDate).to.be.equal(proposalExpirationDate) expect(proposalDataAfter.ownerId).to.be.equal(bobTlId) expect(proposalDataAfter.status.toString()).to.be.equal('0') + expect(proposalDataAfter.referrerId).to.be.equal(0) expect(tx) .to.emit(talentLayerService, 'ProposalCreatedWithoutToken') - .withArgs(1, bobTlId, cid2, 'Pending', 15, alicePlatformId, proposalExpirationDate) + .withArgs(1, bobTlId, cid2, 'Pending', 15, alicePlatformId, proposalExpirationDate, 0) }) it("Bob can't create another proposal for the same service", async function () { @@ -1099,6 +1100,7 @@ describe('TalentLayer protocol global testing', function () { // @dev: This field is deprecated and should always be zero address expect(proposalDataAfter.rateToken.toString()).to.be.equal(ethers.constants.AddressZero) expect(proposalDataAfter.dataUri).to.be.equal(cid) + expect(proposalDataAfter.referrerId).to.be.equal(aliceTlId) }) it("Bob can't update his proposal with an amount which is too low", async function () { From 392fa2093a0f3ba42c7cd89ed33d9d31e4aa41a8 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Thu, 8 Jun 2023 08:20:48 +0200 Subject: [PATCH 28/99] Added new test for new function Signed-off-by: Quentin D.C --- test/batch/fullWorkflow.ts | 60 +++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index 161ce118..8f431e89 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -784,7 +784,7 @@ describe('TalentLayer protocol global testing', function () { await expect(tx).to.be.revertedWith('Token not allowed') }) - it('Alice the buyer can create a few Open service', async function () { + it('Alice the buyer can create a few Open services', async function () { const platform = await talentLayerPlatformID.getPlatform(alicePlatformId) const alicePlatformServicePostingFee = platform.servicePostingFee @@ -1030,6 +1030,64 @@ describe('TalentLayer protocol global testing', function () { .withArgs(1, bobTlId, cid2, 'Pending', 15, alicePlatformId, proposalExpirationDate, 0) }) + it('Carol can create a proposal with a referrer', async function () { + // Proposal on the Open service n 4 + const platform = await talentLayerPlatformID.getPlatform(alicePlatformId) + const alicePlatformProposalPostingFee = platform.servicePostingFee + + // Proposal data check before the proposal + const proposalDataBefore = await talentLayerService.getProposal(4, carolTlId) + expect(proposalDataBefore.ownerId.toString()).to.be.equal('0') + + // Carol creates a proposal on Platform 1 + const signature = await getSignatureForProposal(platformOneOwner, carolTlId, 4, cid2) + const tx = await talentLayerService + .connect(carol) + .createProposalWithReferrer( + carolTlId, + 4, + 15, + alicePlatformId, + cid2, + proposalExpirationDate, + signature, + carolTlId, + { + value: alicePlatformProposalPostingFee, + }, + ) + + const serviceData = await talentLayerService.services(4) + const proposalDataAfter = await talentLayerService.getProposal(4, carolTlId) + + // Service data check + expect(serviceData.status).to.be.equal(ServiceStatus.Opened) + expect(serviceData.ownerId).to.be.equal(aliceTlId) + + // Proposal data check after the proposal + // @dev: rateToken field not used any more + expect(proposalDataAfter.rateToken).to.be.equal(ethers.constants.AddressZero) + expect(proposalDataAfter.rateAmount.toString()).to.be.equal('15') + expect(proposalDataAfter.dataUri).to.be.equal(cid2) + expect(proposalDataAfter.platformId).to.be.equal(alicePlatformId) + expect(proposalDataAfter.expirationDate).to.be.equal(proposalExpirationDate) + expect(proposalDataAfter.ownerId).to.be.equal(carolTlId) + expect(proposalDataAfter.status.toString()).to.be.equal('0') + expect(proposalDataAfter.referrerId.toString()).to.be.equal(carolTlId.toString()) + expect(tx) + .to.emit(talentLayerService, 'ProposalCreatedWithoutToken') + .withArgs( + 1, + bobTlId, + cid2, + 'Pending', + 15, + alicePlatformId, + proposalExpirationDate, + carolTlId, + ) + }) + it("Bob can't create another proposal for the same service", async function () { const platform = await talentLayerPlatformID.getPlatform(alicePlatformId) const alicePlatformProposalPostingFee = platform.servicePostingFee From 7ed97d85bb5e1654bc74efb83a15f4cc7e2d6f57 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Thu, 8 Jun 2023 14:58:46 +0200 Subject: [PATCH 29/99] Added id check Signed-off-by: Quentin D.C --- contracts/TalentLayerService.sol | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/contracts/TalentLayerService.sol b/contracts/TalentLayerService.sol index 77deac0f..442870ed 100644 --- a/contracts/TalentLayerService.sol +++ b/contracts/TalentLayerService.sol @@ -244,7 +244,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU uint256 public nextServiceId; /** - * @notice TalentLayerId address + * @notice TalentLayerId contract */ ITalentLayerID private tlId; @@ -462,7 +462,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU uint256 _expirationDate, bytes calldata _signature ) public payable onlyOwnerOrDelegate(_profileId) { - _validateProposal(_profileId, _serviceId, _rateAmount, _platformId, _dataUri, _signature); + _validateProposal(_profileId, _serviceId, _rateAmount, _platformId, _dataUri, _signature, 0); proposals[_serviceId][_profileId] = Proposal({ status: ProposalStatus.Pending, @@ -513,7 +513,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU bytes calldata _signature, uint256 _referrerId ) public payable onlyOwnerOrDelegate(_profileId) { - _validateProposal(_profileId, _serviceId, _rateAmount, _platformId, _dataUri, _signature); + _validateProposal(_profileId, _serviceId, _rateAmount, _platformId, _dataUri, _signature, _referrerId); proposals[_serviceId][_profileId] = Proposal({ status: ProposalStatus.Pending, @@ -568,6 +568,10 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU require(proposal.status != ProposalStatus.Validated, "Already validated"); require(_rateAmount >= allowedTokenList[service.token].minimumTransactionAmount, "Amount too low"); + if (_referrerId != 0) { + tlId.isValid(_referrerId); + } + proposal.rateAmount = _rateAmount; proposal.dataUri = _dataUri; proposal.expirationDate = _expirationDate; @@ -757,7 +761,8 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU uint256 _rateAmount, uint256 _platformId, string calldata _dataUri, - bytes calldata _signature + bytes calldata _signature, + uint256 _referrerId ) private view { uint256 proposalPostingFee = talentLayerPlatformIdContract.getProposalPostingFee(_platformId); require(msg.value == proposalPostingFee, "Non-matching funds"); @@ -776,6 +781,10 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU bytes32 messageHash = keccak256(abi.encodePacked("createProposal", _profileId, ";", _serviceId, _dataUri)); _validatePlatformSignature(_signature, messageHash, platformSigner); } + + if (_referrerId != 0) { + tlId.isValid(_referrerId); + } } /** From cb39a5b6fe6efccdc1760e271169a01fc6d93e93 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Thu, 8 Jun 2023 14:58:58 +0200 Subject: [PATCH 30/99] Added id check tests Signed-off-by: Quentin D.C --- test/batch/fullWorkflow.ts | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index 8f431e89..d33a22cc 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -1030,6 +1030,30 @@ describe('TalentLayer protocol global testing', function () { .withArgs(1, bobTlId, cid2, 'Pending', 15, alicePlatformId, proposalExpirationDate, 0) }) + it("Carol can't create a proposal with a non existing referrer id", async function () { + // Proposal on the Open service n 4 + const platform = await talentLayerPlatformID.getPlatform(alicePlatformId) + const alicePlatformProposalPostingFee = platform.servicePostingFee + + const signature = await getSignatureForProposal(platformOneOwner, carolTlId, 4, cid2) + const tx = talentLayerService + .connect(carol) + .createProposalWithReferrer( + carolTlId, + 4, + 15, + alicePlatformId, + cid2, + proposalExpirationDate, + signature, + 99, + { + value: alicePlatformProposalPostingFee, + }, + ) + await expect(tx).to.be.revertedWith('not valid') + }) + it('Carol can create a proposal with a referrer', async function () { // Proposal on the Open service n 4 const platform = await talentLayerPlatformID.getPlatform(alicePlatformId) @@ -1179,6 +1203,18 @@ describe('TalentLayer protocol global testing', function () { await expect(tx).to.be.revertedWith('Amount too low') }) + + it("Bob can't update his proposal with a non-existing referrer id", async function () { + const minTransactionAmount = await ( + await talentLayerService.allowedTokenList(token.address) + ).minimumTransactionAmount + + const tx = talentLayerService + .connect(bob) + .updateProposal(bobTlId, 1, minTransactionAmount, cid, proposalExpirationDate, 99) + + await expect(tx).to.be.revertedWith('not valid') + }) }) describe('Escrow Contract test.', function () { From 56d642f1174a7a04f9599d41504de12bc834e258 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Fri, 9 Jun 2023 07:37:42 +0200 Subject: [PATCH 31/99] Removed rateToken from service metadata Signed-off-by: Quentin D.C --- contracts/interfaces/ITalentLayerService.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/interfaces/ITalentLayerService.sol b/contracts/interfaces/ITalentLayerService.sol index 761e25da..ef14a14c 100644 --- a/contracts/interfaces/ITalentLayerService.sol +++ b/contracts/interfaces/ITalentLayerService.sol @@ -38,6 +38,7 @@ interface ITalentLayerService { uint256 platformId; string dataUri; uint256 expirationDate; + uint256 referrerId; } function getService(uint256 _serviceId) external view returns (Service memory); From 4cab0d9696168d6c2062067f55829066af7b36af Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Fri, 9 Jun 2023 07:39:20 +0200 Subject: [PATCH 32/99] Added 2 new fields to Transaction Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index ec65218f..b620910e 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -88,6 +88,8 @@ contract TalentLayerEscrow is * @param lastInteraction Last interaction for the dispute procedure. * @param arbitratorExtraData Extra data to set up the arbitration. * @param arbitrationFeeTimeout timeout for parties to pay the arbitration fee + * @param referrerId the id of the optional referrer + * @param referralAmount the optional lump sum optional fee to be sent to the referrer */ struct Transaction { uint256 id; @@ -109,6 +111,8 @@ contract TalentLayerEscrow is uint256 lastInteraction; bytes arbitratorExtraData; uint256 arbitrationFeeTimeout; + uint256 referrerId; + uint256 referralAmount; } // =========================== Events ============================== From a26caafc8b276aaa8d9c47c29b78ba2cef784346 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Fri, 9 Jun 2023 07:40:56 +0200 Subject: [PATCH 33/99] Added referralAmount in fees calculations Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index b620910e..dd909e42 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -470,7 +470,8 @@ contract TalentLayerEscrow is uint256 transactionAmount = _calculateTotalWithFees( proposal.rateAmount, originServiceCreationPlatform.originServiceFeeRate, - originProposalCreationPlatform.originValidatedProposalFeeRate + originProposalCreationPlatform.originValidatedProposalFeeRate, + service.referralAmount ); if (service.token == address(0)) { @@ -510,7 +511,9 @@ contract TalentLayerEscrow is status: Status.NoDispute, arbitrator: originServiceCreationPlatform.arbitrator, arbitratorExtraData: originServiceCreationPlatform.arbitratorExtraData, - arbitrationFeeTimeout: originServiceCreationPlatform.arbitrationFeeTimeout + arbitrationFeeTimeout: originServiceCreationPlatform.arbitrationFeeTimeout, + referrerId: proposal.referrerId, + referralAmount: service.referralAmount }); nextTransactionId.increment(); @@ -900,10 +903,17 @@ contract TalentLayerEscrow is */ function _reimburse(uint256 _transactionId, uint256 _amount) private { Transaction storage transaction = transactions[_transactionId]; + uint256 releasedReferralAmount = 0; + + if (transaction.referrerId != 0 && transaction.amount != 0) { + releasedReferralAmount = (_amount / transaction.amount) * transaction.referralAmount; + } + uint256 totalReleaseAmount = _calculateTotalWithFees( _amount, transaction.originServiceFeeRate, - transaction.originValidatedProposalFeeRate + transaction.originValidatedProposalFeeRate, + releasedReferralAmount ); _safeTransferBalance(payable(transaction.sender), transaction.token, totalReleaseAmount); @@ -1011,18 +1021,21 @@ contract TalentLayerEscrow is * @param _amount The core escrow amount * @param _originServiceFeeRate the %fee (per ten thousands) asked by the platform for each service created on the platform * @param _originValidatedProposalFeeRate the %fee (per ten thousands) asked by the platform for each validates service on the platform + * @param _referralAmount the lump sum optional fee to be sent to the referrer, if any * @return totalEscrowAmount The total amount to be paid by the buyer (including all fees + escrow) The amount to transfer */ function _calculateTotalWithFees( uint256 _amount, uint16 _originServiceFeeRate, - uint16 _originValidatedProposalFeeRate + uint16 _originValidatedProposalFeeRate, + uint256 _referralAmount ) private view returns (uint256 totalEscrowAmount) { return _amount + (((_amount * protocolEscrowFeeRate) + (_amount * _originServiceFeeRate) + - (_amount * _originValidatedProposalFeeRate)) / FEE_DIVIDER); + (_amount * _originValidatedProposalFeeRate)) / FEE_DIVIDER) + + _referralAmount; } // =========================== Overrides ============================== From 7a4ba1c6792f628a54101c34b8e1b57f61685d9d Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Fri, 9 Jun 2023 07:41:28 +0200 Subject: [PATCH 34/99] Added referralAmount in fees distribution Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index dd909e42..dfd57af3 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -181,6 +181,14 @@ contract TalentLayerEscrow is uint256 _amount ); + /** + * @notice Emitted after part of a referral amount is released + * @param _referrerId The id of the referrer. + * @param _token The address of the token used for the payment. + * @param _amount The amount released. + */ + event ReferralAmountReleased(uint256 indexed _referrerId, address indexed _token, uint256 _amount); + /** * @notice Emitted when a party has to pay a fee for the dispute or would otherwise be considered as losing. * @param _transactionId The id of the transaction. @@ -946,18 +954,30 @@ contract TalentLayerEscrow is transaction.token ] += originValidatedProposalFeeRate; + uint256 releasedReferralAmount = 0; + + if (transaction.referrerId != 0 && transaction.amount != 0) { + releasedReferralAmount = (_releaseAmount / transaction.amount) * transaction.referralAmount; + //TODO risk of smart contract hack here + // _safeTransferBalance(payable(transaction.referrer), transaction.token, releasedReferralAmount); + platformIdToTokenToBalance[transaction.referrerId][transaction.token] += releasedReferralAmount; + } + emit OriginServiceFeeRateReleased( originServiceCreationPlatformId, transaction.serviceId, transaction.token, originServiceFeeRate ); + emit OriginValidatedProposalFeeRateReleased( originValidatedProposalPlatformId, transaction.serviceId, transaction.token, originServiceFeeRate ); + + emit ReferralAmountReleased(transaction.referrerId, transaction.token, releasedReferralAmount); } /** From 176369d3bd7a4ee7569ddfabaa3d8098efd2b85e Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Fri, 9 Jun 2023 11:47:11 +0200 Subject: [PATCH 35/99] Added test on new fee calculation Signed-off-by: Quentin D.C --- test/batch/fullWorkflow.ts | 113 ++++++++++++++++++++++++++----------- 1 file changed, 79 insertions(+), 34 deletions(-) diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index d33a22cc..88943d78 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -32,6 +32,8 @@ const carolTlId = 3 const alicePlatformId = 1 const bobPlatformId = 2 +const FEE_DIVIDER = 10000 + describe('TalentLayer protocol global testing', function () { // we define the types of the variables we will use let deployer: SignerWithAddress, @@ -845,19 +847,18 @@ describe('TalentLayer protocol global testing', function () { const alicePlatformServicePostingFee = platform.servicePostingFee const signature = await getSignatureForService(platformOneOwner, aliceTlId, 5, cid) - const tx = await talentLayerService - .connect(alice) - .createServiceWithReferral( - aliceTlId, - alicePlatformId, - cid, - signature, - token.address, - referralAmount, - { - value: alicePlatformServicePostingFee, - }, - ) + const tx = await talentLayerService.connect(alice).createServiceWithReferral( + aliceTlId, + alicePlatformId, + cid, + signature, + ethers.constants.AddressZero, + // token.address, + referralAmount, + { + value: alicePlatformServicePostingFee, + }, + ) const service6Data = await talentLayerService.services(6) expect(tx) @@ -1055,7 +1056,7 @@ describe('TalentLayer protocol global testing', function () { }) it('Carol can create a proposal with a referrer', async function () { - // Proposal on the Open service n 4 + // Proposal on the Open service n 6 const platform = await talentLayerPlatformID.getPlatform(alicePlatformId) const alicePlatformProposalPostingFee = platform.servicePostingFee @@ -1069,20 +1070,20 @@ describe('TalentLayer protocol global testing', function () { .connect(carol) .createProposalWithReferrer( carolTlId, - 4, + 6, 15, alicePlatformId, cid2, proposalExpirationDate, signature, - carolTlId, + bobTlId, { value: alicePlatformProposalPostingFee, }, ) - const serviceData = await talentLayerService.services(4) - const proposalDataAfter = await talentLayerService.getProposal(4, carolTlId) + const serviceData = await talentLayerService.services(6) + const proposalDataAfter = await talentLayerService.getProposal(6, carolTlId) // Service data check expect(serviceData.status).to.be.equal(ServiceStatus.Opened) @@ -1097,7 +1098,7 @@ describe('TalentLayer protocol global testing', function () { expect(proposalDataAfter.expirationDate).to.be.equal(proposalExpirationDate) expect(proposalDataAfter.ownerId).to.be.equal(carolTlId) expect(proposalDataAfter.status.toString()).to.be.equal('0') - expect(proposalDataAfter.referrerId.toString()).to.be.equal(carolTlId.toString()) + expect(proposalDataAfter.referrerId.toString()).to.be.equal(bobTlId.toString()) expect(tx) .to.emit(talentLayerService, 'ProposalCreatedWithoutToken') .withArgs( @@ -1337,7 +1338,7 @@ describe('TalentLayer protocol global testing', function () { amountBob + (amountBob * (protocolEscrowFeeRate + originValidatedProposalFeeRate + originServiceFeeRate)) / - 10000 + FEE_DIVIDER await token.connect(alice).approve(talentLayerEscrow.address, totalAmount) @@ -1482,14 +1483,14 @@ describe('TalentLayer protocol global testing', function () { .getClaimableFeeBalance(token.address) // Alice gets originServiceFeeRate as the service was created on her platform expect(alicePlatformBalance.toString()).to.be.equal( - ((releasedAmount * originServiceFeeRate) / 10000).toString(), + ((releasedAmount * originServiceFeeRate) / FEE_DIVIDER).toString(), ) // Bob gets originProposalValidatedFeeRate as the proposal was validated on his platform expect(bobPlatformBalance.toString()).to.be.equal( - ((releasedAmount * originValidatedProposalFeeRate) / 10000).toString(), + ((releasedAmount * originValidatedProposalFeeRate) / FEE_DIVIDER).toString(), ) expect(deployerBalance.toString()).to.be.equal( - ((releasedAmount * protocolEscrowFeeRate) / 10000).toString(), + ((releasedAmount * protocolEscrowFeeRate) / FEE_DIVIDER).toString(), ) }) @@ -1535,14 +1536,14 @@ describe('TalentLayer protocol global testing', function () { .getClaimableFeeBalance(token.address) // Alice gets originServiceFeeRate as the service was created on her platform expect(alicePlatformBalance.toString()).to.be.equal( - ((((3 * amountBob) / 4) * originServiceFeeRate) / 10000).toString(), + ((((3 * amountBob) / 4) * originServiceFeeRate) / FEE_DIVIDER).toString(), ) // Bob gets originProposalValidatedFeeRate as the proposal was validated on his platform expect(bobPlatformBalance.toString()).to.be.equal( - ((((3 * amountBob) / 4) * originValidatedProposalFeeRate) / 10000).toString(), + ((((3 * amountBob) / 4) * originValidatedProposalFeeRate) / FEE_DIVIDER).toString(), ) expect(deployerBalance.toString()).to.be.equal( - ((((3 * amountBob) / 4) * protocolEscrowFeeRate) / 10000).toString(), + ((((3 * amountBob) / 4) * protocolEscrowFeeRate) / FEE_DIVIDER).toString(), ) }) @@ -1591,7 +1592,7 @@ describe('TalentLayer protocol global testing', function () { amountBob + (amountBob * (protocolEscrowFeeRate + originServiceFeeRate + originValidatedProposalFeeRate)) / - 10000 + FEE_DIVIDER await token.connect(alice).approve(talentLayerEscrow.address, totalAmount) @@ -1713,7 +1714,7 @@ describe('TalentLayer protocol global testing', function () { amountBob + (amountBob * (protocolEscrowFeeRate + originValidatedProposalFeeRate + originServiceFeeRate)) / - 10000 + FEE_DIVIDER // we need to retreive the Bob proposal dataUri const proposal = await talentLayerService.proposals(serviceId, bobTlId) @@ -1830,6 +1831,50 @@ describe('TalentLayer protocol global testing', function () { ).to.be.reverted }) + it("Alice can deposit funds for Carol's proposal including referral amount, which will emit an event.", async function () { + const service = await talentLayerService.services(6) + const proposal = await talentLayerService.proposals(6, carolTlId) + const alicePlatformData = await talentLayerPlatformID.platforms(alicePlatformId) + // const bobPlatformData = await talentLayerPlatformID.platforms(bobPlatformId) + const protocolEscrowFeeRate = await talentLayerEscrow.protocolEscrowFeeRate() + const originServiceFeeRate = alicePlatformData.originServiceFeeRate + const originValidatedProposalFeeRate = alicePlatformData.originValidatedProposalFeeRate + const referralAmount = service.referralAmount + + const totalAmountWithReferral = proposal.rateAmount + .add( + proposal.rateAmount + .mul(protocolEscrowFeeRate) + .add(proposal.rateAmount.mul(originServiceFeeRate)) + .add(proposal.rateAmount.mul(originValidatedProposalFeeRate)) + .div(FEE_DIVIDER), + ) + .add(referralAmount) + + // Fails if value sent is not the total amount + const tx = talentLayerEscrow + .connect(alice) + .createTransaction(6, carolTlId, metaEvidenceCid, proposal.dataUri, { + value: totalAmountWithReferral.sub(BigNumber.from(1)), + }) + await expect(tx).to.be.revertedWith('Non-matching funds') + + // Success if the value sent is the total amount + const tx2 = await talentLayerEscrow + .connect(alice) + .createTransaction(6, carolTlId, metaEvidenceCid, proposal.dataUri, { + value: totalAmountWithReferral, + }) + await expect(tx2).to.changeEtherBalances( + [talentLayerEscrow.address, alice, bob], + [totalAmountWithReferral, -totalAmountWithReferral, 0], + ) + + await expect(tx2) + .to.emit(talentLayerEscrow, 'TransactionCreated') + .to.emit(talentLayerEscrow, 'MetaEvidence') + }) + it('Carol should not be allowed to release escrow the service.', async function () { await expect( talentLayerEscrow.connect(carol).release(carolTlId, transactionId, 10000), @@ -1864,14 +1909,14 @@ describe('TalentLayer protocol global testing', function () { .getClaimableFeeBalance(ethAddress) // Alice gets the originServiceFeeRate as the service was created on her platform expect(alicePlatformBalance.toString()).to.be.equal( - ((releaseAmount * originServiceFeeRate) / 10000).toString(), + ((releaseAmount * originServiceFeeRate) / FEE_DIVIDER).toString(), ) // Bob gets the originValidatedProposalFeeRate as the proposal was created on his platform expect(bobPlatformBalance.toString()).to.be.equal( - ((releaseAmount * originValidatedProposalFeeRate) / 10000).toString(), + ((releaseAmount * originValidatedProposalFeeRate) / FEE_DIVIDER).toString(), ) expect(deployerBalance.toString()).to.be.equal( - ((releaseAmount * protocolEscrowFeeRate) / 10000).toString(), + ((releaseAmount * protocolEscrowFeeRate) / FEE_DIVIDER).toString(), ) }) @@ -1902,14 +1947,14 @@ describe('TalentLayer protocol global testing', function () { .getClaimableFeeBalance(ethAddress) // Alice gets the originServiceFeeRate as the service was created on her platform expect(alicePlatformBalance.toString()).to.be.equal( - ((((3 * amountBob) / 4) * originServiceFeeRate) / 10000).toString(), + ((((3 * amountBob) / 4) * originServiceFeeRate) / FEE_DIVIDER).toString(), ) // Bob gets the originValidatedProposalFeeRate as the proposal was created on his platform expect(bobPlatformBalance.toString()).to.be.equal( - ((((3 * amountBob) / 4) * originValidatedProposalFeeRate) / 10000).toString(), + ((((3 * amountBob) / 4) * originValidatedProposalFeeRate) / FEE_DIVIDER).toString(), ) expect(deployerBalance.toString()).to.be.equal( - ((((3 * amountBob) / 4) * protocolEscrowFeeRate) / 10000).toString(), + ((((3 * amountBob) / 4) * protocolEscrowFeeRate) / FEE_DIVIDER).toString(), ) }) From a8a243a823f865e5c777ba60b73190d782d4c370 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Fri, 9 Jun 2023 15:22:30 +0200 Subject: [PATCH 36/99] Fixed arythmetic bug Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index dfd57af3..cc091cf9 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -913,8 +913,10 @@ contract TalentLayerEscrow is Transaction storage transaction = transactions[_transactionId]; uint256 releasedReferralAmount = 0; - if (transaction.referrerId != 0 && transaction.amount != 0) { - releasedReferralAmount = (_amount / transaction.amount) * transaction.referralAmount; + if (transaction.referrerId != 0) { + releasedReferralAmount = + (_amount * transaction.referralAmount) / + (transaction.amount + transaction.releasedAmount); } uint256 totalReleaseAmount = _calculateTotalWithFees( From ef36da39b233c09af2a6892e4f35c3bd17fbef5f Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Fri, 9 Jun 2023 15:22:49 +0200 Subject: [PATCH 37/99] Gas saving Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index cc091cf9..e555a5ed 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -1052,7 +1052,7 @@ contract TalentLayerEscrow is uint16 _originValidatedProposalFeeRate, uint256 _referralAmount ) private view returns (uint256 totalEscrowAmount) { - return + totalEscrowAmount = _amount + (((_amount * protocolEscrowFeeRate) + (_amount * _originServiceFeeRate) + From fda60261fdc6c1bfda9c51d06d0e889d3050b1fd Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Fri, 9 Jun 2023 15:43:50 +0200 Subject: [PATCH 38/99] Added test 1 for referral release using ETH Signed-off-by: Quentin D.C --- test/batch/fullWorkflow.ts | 49 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index 88943d78..cdbeb8ed 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -1071,7 +1071,7 @@ describe('TalentLayer protocol global testing', function () { .createProposalWithReferrer( carolTlId, 6, - 15, + 20000, alicePlatformId, cid2, proposalExpirationDate, @@ -1092,7 +1092,7 @@ describe('TalentLayer protocol global testing', function () { // Proposal data check after the proposal // @dev: rateToken field not used any more expect(proposalDataAfter.rateToken).to.be.equal(ethers.constants.AddressZero) - expect(proposalDataAfter.rateAmount.toString()).to.be.equal('15') + expect(proposalDataAfter.rateAmount.toString()).to.be.equal('20000') expect(proposalDataAfter.dataUri).to.be.equal(cid2) expect(proposalDataAfter.platformId).to.be.equal(alicePlatformId) expect(proposalDataAfter.expirationDate).to.be.equal(proposalExpirationDate) @@ -1875,6 +1875,51 @@ describe('TalentLayer protocol global testing', function () { .to.emit(talentLayerEscrow, 'MetaEvidence') }) + it('Alice can release half of the escrow to Carol, and fees are correctly split, including referral amount.', async function () { + const transactionDetails = await talentLayerEscrow + .connect(alice) + .getTransactionDetails(carolTlId) + console.log( + 'bobPlatformBalance BEFORE', + await talentLayerEscrow.connect(bob).getClaimableFeeBalance(ethAddress), + ) + const protocolEscrowFeeRate = transactionDetails.protocolEscrowFeeRate + const originServiceFeeRate = transactionDetails.originServiceFeeRate + const originValidatedProposalFeeRate = transactionDetails.originValidatedProposalFeeRate + const releaseAmount = transactionDetails.amount.div(BigNumber.from(2)) + const releasedReferrerAmount = releaseAmount + .mul(transactionDetails.referralAmount) + .div(transactionDetails.amount) + + const transaction = await talentLayerEscrow + .connect(alice) + .release(aliceTlId, carolTlId, releaseAmount) + // Bob gets half of the referral amount + await expect(transaction).to.changeEtherBalances( + [talentLayerEscrow.address, alice, carol, bob], + [-releaseAmount.add(releasedReferrerAmount), 0, releaseAmount, releasedReferrerAmount], + ) + + const alicePlatformBalance = await talentLayerEscrow + .connect(alice) + .getClaimableFeeBalance(ethAddress) + const bobPlatformBalance = await talentLayerEscrow + .connect(bob) + .getClaimableFeeBalance(ethAddress) + const deployerBalance = await talentLayerEscrow + .connect(deployer) + .getClaimableFeeBalance(ethAddress) + // Alice gets half of both the originServiceFeeRate and the originValidatedProposalFeeRate + expect(alicePlatformBalance).to.be.equal( + releaseAmount.mul(originServiceFeeRate + originValidatedProposalFeeRate).div(FEE_DIVIDER), + ) + expect(deployerBalance.toString()).to.be.equal( + releaseAmount.mul(protocolEscrowFeeRate).div(FEE_DIVIDER), + ) + await talentLayerEscrow.connect(alice).claim(alicePlatformId, ethers.constants.AddressZero) + await talentLayerEscrow.connect(deployer).claim(0, ethers.constants.AddressZero) + }) + it('Carol should not be allowed to release escrow the service.', async function () { await expect( talentLayerEscrow.connect(carol).release(carolTlId, transactionId, 10000), From d5291d9532b3fdb2ce854b2bd9c9ac1e2a1dfd54 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Fri, 9 Jun 2023 17:43:45 +0200 Subject: [PATCH 39/99] Modified Escrow transfer function for referral amount Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index e555a5ed..2fe8403c 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -13,6 +13,7 @@ import {ITalentLayerPlatformID} from "./interfaces/ITalentLayerPlatformID.sol"; import "./libs/ERC2771RecipientUpgradeable.sol"; import {IArbitrable} from "./interfaces/IArbitrable.sol"; import {Arbitrator} from "./Arbitrator.sol"; +import "hardhat/console.sol"; /** * @title TalentLayer Escrow Contract @@ -475,6 +476,11 @@ contract TalentLayerEscrow is ? talentLayerPlatformIdContract.getPlatform(proposal.platformId) : originServiceCreationPlatform; + // uint256 referralAmount = service.referralAmount; + // if (transaction.referrer == address(0)) { + // referralAmount = 0; + // } + uint256 transactionAmount = _calculateTotalWithFees( proposal.rateAmount, originServiceCreationPlatform.originServiceFeeRate, @@ -937,6 +943,7 @@ contract TalentLayerEscrow is */ function _distributeFees(uint256 _transactionId, uint256 _releaseAmount) private { Transaction storage transaction = transactions[_transactionId]; + console.log("HARDHAT - transaction.amt %s, _transactionId %s", transaction.amount, _transactionId); ( ITalentLayerService.Service memory service, ITalentLayerService.Proposal memory proposal @@ -958,11 +965,16 @@ contract TalentLayerEscrow is uint256 releasedReferralAmount = 0; - if (transaction.referrerId != 0 && transaction.amount != 0) { - releasedReferralAmount = (_releaseAmount / transaction.amount) * transaction.referralAmount; - //TODO risk of smart contract hack here - // _safeTransferBalance(payable(transaction.referrer), transaction.token, releasedReferralAmount); - platformIdToTokenToBalance[transaction.referrerId][transaction.token] += releasedReferralAmount; + //TODO ca amount be 0? Not as long as min amount in service contract + if (transaction.referrerId != 0) { + releasedReferralAmount = + (_releaseAmount * transaction.referralAmount) / + (transaction.amount + transaction.releasedAmount); + _safeTransferBalance( + payable(talentLayerIdContract.ownerOf(transaction.referrerId)), + transaction.token, + releasedReferralAmount + ); } emit OriginServiceFeeRateReleased( From 754725e7c2c218e76d6353b85421d42ba2e5d425 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Fri, 9 Jun 2023 17:45:54 +0200 Subject: [PATCH 40/99] Added tests for release function using ERC20 & ETH Signed-off-by: Quentin D.C --- test/batch/fullWorkflow.ts | 283 ++++++++++++++++++++++++++++++++++--- 1 file changed, 261 insertions(+), 22 deletions(-) diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index cdbeb8ed..1487b9ae 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -842,7 +842,7 @@ describe('TalentLayer protocol global testing', function () { expect(service1Data.referralAmount).to.be.equal(0) }) - it('Alice the buyer can create a service with referral', async function () { + it('Alice the buyer can create a service using ETH with referral', async function () { const platform = await talentLayerPlatformID.getPlatform(alicePlatformId) const alicePlatformServicePostingFee = platform.servicePostingFee @@ -863,15 +863,48 @@ describe('TalentLayer protocol global testing', function () { expect(tx) .to.emit(talentLayerService, 'ServiceCreatedWithReferral') - .withArgs(5, aliceTlId, alicePlatformId, cid, token.address, referralAmount) + .withArgs(6, aliceTlId, alicePlatformId, cid, token.address, referralAmount) expect(service6Data.status).to.be.equal(ServiceStatus.Opened) expect(service6Data.ownerId).to.be.equal(aliceTlId) + expect(service6Data.token).to.be.equal(ethers.constants.AddressZero) expect(service6Data.dataUri).to.be.equal(cid) expect(service6Data.platformId).to.be.equal(1) expect(service6Data.referralAmount).to.be.equal(referralAmount) }) + it('Alice the buyer can create a service using ERC20 Token with referral', async function () { + const platform = await talentLayerPlatformID.getPlatform(alicePlatformId) + const alicePlatformServicePostingFee = platform.servicePostingFee + + const signature = await getSignatureForService(platformOneOwner, aliceTlId, 6, cid) + const tx = await talentLayerService + .connect(alice) + .createServiceWithReferral( + aliceTlId, + alicePlatformId, + cid, + signature, + token.address, + referralAmount, + { + value: alicePlatformServicePostingFee, + }, + ) + const service7Data = await talentLayerService.services(7) + + expect(tx) + .to.emit(talentLayerService, 'ServiceCreatedWithReferral') + .withArgs(7, aliceTlId, alicePlatformId, cid, token.address, referralAmount) + + expect(service7Data.status).to.be.equal(ServiceStatus.Opened) + expect(service7Data.ownerId).to.be.equal(aliceTlId) + expect(service7Data.token).to.be.equal(token.address) + expect(service7Data.dataUri).to.be.equal(cid) + expect(service7Data.platformId).to.be.equal(1) + expect(service7Data.referralAmount).to.be.equal(referralAmount) + }) + it("Alice can't create a new open service with wrong TalentLayer Platform ID", async function () { const signature = await getSignatureForService(platformOneOwner, aliceTlId, 5, cid) await expect( @@ -1055,17 +1088,17 @@ describe('TalentLayer protocol global testing', function () { await expect(tx).to.be.revertedWith('not valid') }) - it('Carol can create a proposal with a referrer', async function () { + it('Carol can create a proposal with a referrer for a service using ETH', async function () { // Proposal on the Open service n 6 const platform = await talentLayerPlatformID.getPlatform(alicePlatformId) const alicePlatformProposalPostingFee = platform.servicePostingFee // Proposal data check before the proposal - const proposalDataBefore = await talentLayerService.getProposal(4, carolTlId) + const proposalDataBefore = await talentLayerService.getProposal(6, carolTlId) expect(proposalDataBefore.ownerId.toString()).to.be.equal('0') // Carol creates a proposal on Platform 1 - const signature = await getSignatureForProposal(platformOneOwner, carolTlId, 4, cid2) + const signature = await getSignatureForProposal(platformOneOwner, carolTlId, 6, cid2) const tx = await talentLayerService .connect(carol) .createProposalWithReferrer( @@ -1102,7 +1135,65 @@ describe('TalentLayer protocol global testing', function () { expect(tx) .to.emit(talentLayerService, 'ProposalCreatedWithoutToken') .withArgs( - 1, + 6, + bobTlId, + cid2, + 'Pending', + 15, + alicePlatformId, + proposalExpirationDate, + carolTlId, + ) + }) + + it('Carol can create a proposal with a referrer for a service using ERC20 token', async function () { + // Proposal on the Open service n 7 + const platform = await talentLayerPlatformID.getPlatform(alicePlatformId) + const alicePlatformProposalPostingFee = platform.servicePostingFee + + // Proposal data check before the proposal + const proposalDataBefore = await talentLayerService.getProposal(4, carolTlId) + expect(proposalDataBefore.ownerId.toString()).to.be.equal('0') + + // Carol creates a proposal on Platform 1 + const signature = await getSignatureForProposal(platformOneOwner, carolTlId, 7, cid2) + const tx = await talentLayerService + .connect(carol) + .createProposalWithReferrer( + carolTlId, + 7, + 20000, + alicePlatformId, + cid2, + proposalExpirationDate, + signature, + bobTlId, + { + value: alicePlatformProposalPostingFee, + }, + ) + + const serviceData = await talentLayerService.services(7) + const proposalDataAfter = await talentLayerService.getProposal(7, carolTlId) + + // Service data check + expect(serviceData.status).to.be.equal(ServiceStatus.Opened) + expect(serviceData.ownerId).to.be.equal(aliceTlId) + + // Proposal data check after the proposal + // @dev: rateToken field not used any more + expect(proposalDataAfter.rateToken).to.be.equal(ethers.constants.AddressZero) + expect(proposalDataAfter.rateAmount.toString()).to.be.equal('20000') + expect(proposalDataAfter.dataUri).to.be.equal(cid2) + expect(proposalDataAfter.platformId).to.be.equal(alicePlatformId) + expect(proposalDataAfter.expirationDate).to.be.equal(proposalExpirationDate) + expect(proposalDataAfter.ownerId).to.be.equal(carolTlId) + expect(proposalDataAfter.status.toString()).to.be.equal('0') + expect(proposalDataAfter.referrerId.toString()).to.be.equal(bobTlId.toString()) + expect(tx) + .to.emit(talentLayerService, 'ProposalCreatedWithoutToken') + .withArgs( + 7, bobTlId, cid2, 'Pending', @@ -1445,6 +1536,120 @@ describe('TalentLayer protocol global testing', function () { await expect(tx).to.be.revertedWith('Amount too low') }) + it("Alice can deposit funds for Carol's proposal for service 7 including referral amount, which will emit an event.", async function () { + const service = await talentLayerService.services(7) + const proposal = await talentLayerService.proposals(7, carolTlId) + const alicePlatformData = await talentLayerPlatformID.platforms(alicePlatformId) + // const bobPlatformData = await talentLayerPlatformID.platforms(bobPlatformId) + const protocolEscrowFeeRate = await talentLayerEscrow.protocolEscrowFeeRate() + const originServiceFeeRate = alicePlatformData.originServiceFeeRate + const originValidatedProposalFeeRate = alicePlatformData.originValidatedProposalFeeRate + const referralAmount = service.referralAmount + + const totalAmountWithReferral = proposal.rateAmount + .add( + proposal.rateAmount + .mul(protocolEscrowFeeRate) + .add(proposal.rateAmount.mul(originServiceFeeRate)) + .add(proposal.rateAmount.mul(originValidatedProposalFeeRate)) + .div(FEE_DIVIDER), + ) + .add(referralAmount) + + await token.connect(alice).approve(talentLayerEscrow.address, totalAmountWithReferral) + + // Success if the value sent is the total amount - transactionId: 2 + const tx = await talentLayerEscrow + .connect(alice) + .createTransaction(7, carolTlId, metaEvidenceCid, proposal.dataUri) + await expect(tx).to.changeTokenBalances( + token, + [talentLayerEscrow.address, alice, bob], + [totalAmountWithReferral, -totalAmountWithReferral, 0], + ) + + await expect(tx) + .to.emit(talentLayerEscrow, 'TransactionCreated') + .to.emit(talentLayerEscrow, 'MetaEvidence') + }) + + it('Alice can release 90% of the escrow to Carol for service 7 which includes a referral amount, and fees are correctly split, including referral amount.', async function () { + const transactionDetails = await talentLayerEscrow.connect(alice).getTransactionDetails(2) + const protocolEscrowFeeRate = transactionDetails.protocolEscrowFeeRate + const originServiceFeeRate = transactionDetails.originServiceFeeRate + const originValidatedProposalFeeRate = transactionDetails.originValidatedProposalFeeRate + const releaseAmount = transactionDetails.amount + .add(transactionDetails.releasedAmount) + .mul(BigNumber.from(9)) + .div(BigNumber.from(10)) + const releasedReferrerAmount = releaseAmount + .mul(transactionDetails.referralAmount) + .div(transactionDetails.amount) + + const tx = await talentLayerEscrow.connect(alice).release(aliceTlId, 2, releaseAmount) + // Bob gets half of the referral amount + await expect(tx).to.changeTokenBalances( + token, + [talentLayerEscrow.address, alice, carol, bob], + [-releaseAmount.add(releasedReferrerAmount), 0, releaseAmount, releasedReferrerAmount], + ) + + const alicePlatformBalance = await talentLayerEscrow + .connect(alice) + .getClaimableFeeBalance(token.address) + const deployerBalance = await talentLayerEscrow + .connect(deployer) + .getClaimableFeeBalance(token.address) + // Alice gets half of both the originServiceFeeRate and the originValidatedProposalFeeRate + expect(alicePlatformBalance).to.be.equal( + releaseAmount.mul(originServiceFeeRate + originValidatedProposalFeeRate).div(FEE_DIVIDER), + ) + expect(deployerBalance.toString()).to.be.equal( + releaseAmount.mul(protocolEscrowFeeRate).div(FEE_DIVIDER), + ) + await talentLayerEscrow.connect(alice).claim(alicePlatformId, token.address) + await talentLayerEscrow.connect(deployer).claim(0, token.address) + }) + + it('Alice can release the remaining 10% of the escrow (inferior to FEE_DIVIDER value) to Carol, and fees are correctly split, including referral amount.', async function () { + const transactionDetails = await talentLayerEscrow.connect(alice).getTransactionDetails(2) + const protocolEscrowFeeRate = transactionDetails.protocolEscrowFeeRate + const originServiceFeeRate = transactionDetails.originServiceFeeRate + const originValidatedProposalFeeRate = transactionDetails.originValidatedProposalFeeRate + const releaseAmount = transactionDetails.amount + const releasedReferrerAmount = releaseAmount + .mul(transactionDetails.referralAmount) + .div(transactionDetails.amount.add(transactionDetails.releasedAmount)) + + const tx = await talentLayerEscrow.connect(alice).release(aliceTlId, 2, releaseAmount) + // Bob gets half of the referral amount + await expect(tx).to.changeTokenBalances( + token, + [talentLayerEscrow.address, alice, carol, bob], + [-releaseAmount.add(releasedReferrerAmount), 0, releaseAmount, releasedReferrerAmount], + ) + + const alicePlatformBalance = await talentLayerEscrow + .connect(alice) + .getClaimableFeeBalance(token.address) + const deployerBalance = await talentLayerEscrow + .connect(deployer) + .getClaimableFeeBalance(token.address) + // Alice gets half of both the originServiceFeeRate and the originValidatedProposalFeeRate + expect(alicePlatformBalance).to.be.equal( + releaseAmount.mul(originServiceFeeRate + originValidatedProposalFeeRate).div(FEE_DIVIDER), + ) + expect(deployerBalance.toString()).to.be.equal( + releaseAmount.mul(protocolEscrowFeeRate).div(FEE_DIVIDER), + ) + await talentLayerEscrow.connect(alice).claim(alicePlatformId, token.address) + await talentLayerEscrow.connect(deployer).claim(0, token.address) + + // Service status is finished + const serviceData = await talentLayerService.services(transactionDetails.serviceId) + expect(serviceData.status).to.equal(2) + }) + it('Alice can release half of the escrow to bob, and fees are correctly split.', async function () { const transactionDetailsBefore = await talentLayerEscrow .connect(alice) @@ -1553,7 +1758,7 @@ describe('TalentLayer protocol global testing', function () { const alicePlatformProposalPostingFee = platform.proposalPostingFee // Create the service - const serviceId = 7 + const serviceId = 8 const signature = await getSignatureForService(platformOneOwner, aliceTlId, 5, cid) await talentLayerService .connect(alice) @@ -1691,7 +1896,7 @@ describe('TalentLayer protocol global testing', function () { const amountBob = 1000000 const amountCarol = 200 const serviceId = 3 - const transactionId = 2 + const transactionId = 3 let proposalIdBob = 0 //Will be set later let proposalIdCarol = 0 //Will be set later let totalAmount = 0 //Will be set later @@ -1831,7 +2036,7 @@ describe('TalentLayer protocol global testing', function () { ).to.be.reverted }) - it("Alice can deposit funds for Carol's proposal including referral amount, which will emit an event.", async function () { + it("Alice can deposit funds for Carol's proposal for service 6 including referral amount, which will emit an event.", async function () { const service = await talentLayerService.services(6) const proposal = await talentLayerService.proposals(6, carolTlId) const alicePlatformData = await talentLayerPlatformID.platforms(alicePlatformId) @@ -1859,7 +2064,7 @@ describe('TalentLayer protocol global testing', function () { }) await expect(tx).to.be.revertedWith('Non-matching funds') - // Success if the value sent is the total amount + // Success if the value sent is the total amount - transactionId: 4 const tx2 = await talentLayerEscrow .connect(alice) .createTransaction(6, carolTlId, metaEvidenceCid, proposal.dataUri, { @@ -1875,25 +2080,22 @@ describe('TalentLayer protocol global testing', function () { .to.emit(talentLayerEscrow, 'MetaEvidence') }) - it('Alice can release half of the escrow to Carol, and fees are correctly split, including referral amount.', async function () { - const transactionDetails = await talentLayerEscrow - .connect(alice) - .getTransactionDetails(carolTlId) - console.log( - 'bobPlatformBalance BEFORE', - await talentLayerEscrow.connect(bob).getClaimableFeeBalance(ethAddress), - ) + it('Alice can release 90% of the escrow to Carol for service 6 which includes a referral amount, and fees are correctly split, including referral amount.', async function () { + const transactionDetails = await talentLayerEscrow.connect(alice).getTransactionDetails(4) const protocolEscrowFeeRate = transactionDetails.protocolEscrowFeeRate const originServiceFeeRate = transactionDetails.originServiceFeeRate const originValidatedProposalFeeRate = transactionDetails.originValidatedProposalFeeRate - const releaseAmount = transactionDetails.amount.div(BigNumber.from(2)) + const releaseAmount = transactionDetails.amount + .add(transactionDetails.releasedAmount) + .mul(BigNumber.from(9)) + .div(BigNumber.from(10)) const releasedReferrerAmount = releaseAmount .mul(transactionDetails.referralAmount) .div(transactionDetails.amount) const transaction = await talentLayerEscrow .connect(alice) - .release(aliceTlId, carolTlId, releaseAmount) + .release(aliceTlId, 4, releaseAmount) // Bob gets half of the referral amount await expect(transaction).to.changeEtherBalances( [talentLayerEscrow.address, alice, carol, bob], @@ -1903,8 +2105,41 @@ describe('TalentLayer protocol global testing', function () { const alicePlatformBalance = await talentLayerEscrow .connect(alice) .getClaimableFeeBalance(ethAddress) - const bobPlatformBalance = await talentLayerEscrow - .connect(bob) + const deployerBalance = await talentLayerEscrow + .connect(deployer) + .getClaimableFeeBalance(ethAddress) + // Alice gets half of both the originServiceFeeRate and the originValidatedProposalFeeRate + expect(alicePlatformBalance).to.be.equal( + releaseAmount.mul(originServiceFeeRate + originValidatedProposalFeeRate).div(FEE_DIVIDER), + ) + expect(deployerBalance.toString()).to.be.equal( + releaseAmount.mul(protocolEscrowFeeRate).div(FEE_DIVIDER), + ) + await talentLayerEscrow.connect(alice).claim(alicePlatformId, ethers.constants.AddressZero) + await talentLayerEscrow.connect(deployer).claim(0, ethers.constants.AddressZero) + }) + + it('Alice can release the remaining 10% of the escrow (inferior to FEE_DIVIDER value) to Carol, and fees are correctly split, including referral amount.', async function () { + const transactionDetails = await talentLayerEscrow.connect(alice).getTransactionDetails(4) + const protocolEscrowFeeRate = transactionDetails.protocolEscrowFeeRate + const originServiceFeeRate = transactionDetails.originServiceFeeRate + const originValidatedProposalFeeRate = transactionDetails.originValidatedProposalFeeRate + const releaseAmount = transactionDetails.amount + const releasedReferrerAmount = releaseAmount + .mul(transactionDetails.referralAmount) + .div(transactionDetails.amount.add(transactionDetails.releasedAmount)) + + const transaction = await talentLayerEscrow + .connect(alice) + .release(aliceTlId, 4, releaseAmount) + // Bob gets half of the referral amount + await expect(transaction).to.changeEtherBalances( + [talentLayerEscrow.address, alice, carol, bob], + [-releaseAmount.add(releasedReferrerAmount), 0, releaseAmount, releasedReferrerAmount], + ) + + const alicePlatformBalance = await talentLayerEscrow + .connect(alice) .getClaimableFeeBalance(ethAddress) const deployerBalance = await talentLayerEscrow .connect(deployer) @@ -1918,6 +2153,10 @@ describe('TalentLayer protocol global testing', function () { ) await talentLayerEscrow.connect(alice).claim(alicePlatformId, ethers.constants.AddressZero) await talentLayerEscrow.connect(deployer).claim(0, ethers.constants.AddressZero) + + // Service status is finished + const serviceData = await talentLayerService.services(transactionDetails.serviceId) + expect(serviceData.status).to.equal(2) }) it('Carol should not be allowed to release escrow the service.', async function () { From ecefa0ce2f78a9ef1150b12c54a980acacd5e191 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Fri, 9 Jun 2023 23:33:53 +0200 Subject: [PATCH 41/99] Had to add "uint256 totalAmount" field to Transaction struct, in order to calculate referral amount reimbursement amounts. Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 25 ++++----- test/batch/fullWorkflow.ts | 99 ++++++++++++++++++++++++++++----- 2 files changed, 95 insertions(+), 29 deletions(-) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index 2fe8403c..300cf430 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -74,7 +74,8 @@ contract TalentLayerEscrow is * @param sender The party paying the escrow amount * @param receiver The intended receiver of the escrow amount * @param token The token used for the transaction - * @param amount The amount of the transaction EXCLUDING FEES + * @param amount The amount of the transaction EXCLUDING FEES (will not vary) + * @param amount The amount of the transaction EXCLUDING FEES (will diminish after each release payment) * @param releasedAmount The amount of the transaction that has been released to the receiver EXCLUDING FEES * @param serviceId The ID of the associated service * @param proposalId The id of the validated proposal @@ -97,6 +98,7 @@ contract TalentLayerEscrow is address sender; address receiver; address token; + uint256 totalAmount; uint256 amount; uint256 releasedAmount; uint256 serviceId; @@ -511,6 +513,7 @@ contract TalentLayerEscrow is sender: sender, receiver: receiver, token: service.token, + totalAmount: proposal.rateAmount, amount: proposal.rateAmount, releasedAmount: 0, serviceId: _serviceId, @@ -917,21 +920,18 @@ contract TalentLayerEscrow is */ function _reimburse(uint256 _transactionId, uint256 _amount) private { Transaction storage transaction = transactions[_transactionId]; - uint256 releasedReferralAmount = 0; + uint256 reimbursedReferralAmount = 0; if (transaction.referrerId != 0) { - releasedReferralAmount = - (_amount * transaction.referralAmount) / - (transaction.amount + transaction.releasedAmount); + reimbursedReferralAmount = (_amount * transaction.referralAmount) / (transaction.totalAmount); } - - uint256 totalReleaseAmount = _calculateTotalWithFees( + uint256 totalReimburseAmount = _calculateTotalWithFees( _amount, transaction.originServiceFeeRate, transaction.originValidatedProposalFeeRate, - releasedReferralAmount + reimbursedReferralAmount ); - _safeTransferBalance(payable(transaction.sender), transaction.token, totalReleaseAmount); + _safeTransferBalance(payable(transaction.sender), transaction.token, totalReimburseAmount); _afterPayment(_transactionId, PaymentType.Reimburse, _amount); } @@ -943,7 +943,6 @@ contract TalentLayerEscrow is */ function _distributeFees(uint256 _transactionId, uint256 _releaseAmount) private { Transaction storage transaction = transactions[_transactionId]; - console.log("HARDHAT - transaction.amt %s, _transactionId %s", transaction.amount, _transactionId); ( ITalentLayerService.Service memory service, ITalentLayerService.Proposal memory proposal @@ -965,11 +964,9 @@ contract TalentLayerEscrow is uint256 releasedReferralAmount = 0; - //TODO ca amount be 0? Not as long as min amount in service contract + //TODO can amount be 0? Not as long as min amount in service contract if (transaction.referrerId != 0) { - releasedReferralAmount = - (_releaseAmount * transaction.referralAmount) / - (transaction.amount + transaction.releasedAmount); + releasedReferralAmount = (_releaseAmount * transaction.referralAmount) / (transaction.totalAmount); _safeTransferBalance( payable(talentLayerIdContract.ownerOf(transaction.referrerId)), transaction.token, diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index 1487b9ae..3434d42b 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -34,7 +34,7 @@ const bobPlatformId = 2 const FEE_DIVIDER = 10000 -describe('TalentLayer protocol global testing', function () { +describe.only('TalentLayer protocol global testing', function () { // we define the types of the variables we will use let deployer: SignerWithAddress, alice: SignerWithAddress, @@ -1104,7 +1104,7 @@ describe('TalentLayer protocol global testing', function () { .createProposalWithReferrer( carolTlId, 6, - 20000, + 2000000, alicePlatformId, cid2, proposalExpirationDate, @@ -1125,7 +1125,7 @@ describe('TalentLayer protocol global testing', function () { // Proposal data check after the proposal // @dev: rateToken field not used any more expect(proposalDataAfter.rateToken).to.be.equal(ethers.constants.AddressZero) - expect(proposalDataAfter.rateAmount.toString()).to.be.equal('20000') + expect(proposalDataAfter.rateAmount.toString()).to.be.equal('2000000') expect(proposalDataAfter.dataUri).to.be.equal(cid2) expect(proposalDataAfter.platformId).to.be.equal(alicePlatformId) expect(proposalDataAfter.expirationDate).to.be.equal(proposalExpirationDate) @@ -1162,7 +1162,7 @@ describe('TalentLayer protocol global testing', function () { .createProposalWithReferrer( carolTlId, 7, - 20000, + 2000000, alicePlatformId, cid2, proposalExpirationDate, @@ -1183,7 +1183,7 @@ describe('TalentLayer protocol global testing', function () { // Proposal data check after the proposal // @dev: rateToken field not used any more expect(proposalDataAfter.rateToken).to.be.equal(ethers.constants.AddressZero) - expect(proposalDataAfter.rateAmount.toString()).to.be.equal('20000') + expect(proposalDataAfter.rateAmount.toString()).to.be.equal('2000000') expect(proposalDataAfter.dataUri).to.be.equal(cid2) expect(proposalDataAfter.platformId).to.be.equal(alicePlatformId) expect(proposalDataAfter.expirationDate).to.be.equal(proposalExpirationDate) @@ -1573,15 +1573,15 @@ describe('TalentLayer protocol global testing', function () { .to.emit(talentLayerEscrow, 'MetaEvidence') }) - it('Alice can release 90% of the escrow to Carol for service 7 which includes a referral amount, and fees are correctly split, including referral amount.', async function () { + it('Alice can release 50% of the escrow to Carol for service 7 which includes a referral amount, and fees are correctly split.', async function () { const transactionDetails = await talentLayerEscrow.connect(alice).getTransactionDetails(2) const protocolEscrowFeeRate = transactionDetails.protocolEscrowFeeRate const originServiceFeeRate = transactionDetails.originServiceFeeRate const originValidatedProposalFeeRate = transactionDetails.originValidatedProposalFeeRate const releaseAmount = transactionDetails.amount .add(transactionDetails.releasedAmount) - .mul(BigNumber.from(9)) - .div(BigNumber.from(10)) + .mul(BigNumber.from(1)) + .div(BigNumber.from(2)) const releasedReferrerAmount = releaseAmount .mul(transactionDetails.referralAmount) .div(transactionDetails.amount) @@ -1611,6 +1611,37 @@ describe('TalentLayer protocol global testing', function () { await talentLayerEscrow.connect(deployer).claim(0, token.address) }) + it('Alice can reimburse 40% of the escrow to Carol for service 7 which includes a referral amount.', async function () { + const transactionDetails = await talentLayerEscrow.connect(alice).getTransactionDetails(2) + const protocolEscrowFeeRate = transactionDetails.protocolEscrowFeeRate + const originServiceFeeRate = transactionDetails.originServiceFeeRate + const originValidatedProposalFeeRate = transactionDetails.originValidatedProposalFeeRate + const reimburseAmount = transactionDetails.totalAmount + .mul(BigNumber.from(4)) + .div(BigNumber.from(10)) + + const reimburseReferrerAmount = reimburseAmount + .mul(transactionDetails.referralAmount) + .div(transactionDetails.totalAmount) + const reimburseFeesAMount = reimburseAmount + .mul(protocolEscrowFeeRate) + .add(reimburseAmount.mul(originServiceFeeRate)) + .add(reimburseAmount.mul(originValidatedProposalFeeRate)) + .div(FEE_DIVIDER) + + const totalReimburseAmount = reimburseAmount + .add(reimburseReferrerAmount) + .add(reimburseFeesAMount) + + const tx = await talentLayerEscrow.connect(carol).reimburse(carolTlId, 2, reimburseAmount) + // Alice gets back: 40% of all 3 fees + 40% of referralAmount + await expect(tx).to.changeTokenBalances( + token, + [talentLayerEscrow.address, alice], + [-totalReimburseAmount, totalReimburseAmount], + ) + }) + it('Alice can release the remaining 10% of the escrow (inferior to FEE_DIVIDER value) to Carol, and fees are correctly split, including referral amount.', async function () { const transactionDetails = await talentLayerEscrow.connect(alice).getTransactionDetails(2) const protocolEscrowFeeRate = transactionDetails.protocolEscrowFeeRate @@ -1619,7 +1650,7 @@ describe('TalentLayer protocol global testing', function () { const releaseAmount = transactionDetails.amount const releasedReferrerAmount = releaseAmount .mul(transactionDetails.referralAmount) - .div(transactionDetails.amount.add(transactionDetails.releasedAmount)) + .div(transactionDetails.totalAmount) const tx = await talentLayerEscrow.connect(alice).release(aliceTlId, 2, releaseAmount) // Bob gets half of the referral amount @@ -1647,7 +1678,11 @@ describe('TalentLayer protocol global testing', function () { // Service status is finished const serviceData = await talentLayerService.services(transactionDetails.serviceId) + const transactionDetailsAfter = await talentLayerEscrow + .connect(alice) + .getTransactionDetails(2) expect(serviceData.status).to.equal(2) + expect(transactionDetailsAfter.amount).to.equal(0) }) it('Alice can release half of the escrow to bob, and fees are correctly split.', async function () { @@ -2080,15 +2115,15 @@ describe('TalentLayer protocol global testing', function () { .to.emit(talentLayerEscrow, 'MetaEvidence') }) - it('Alice can release 90% of the escrow to Carol for service 6 which includes a referral amount, and fees are correctly split, including referral amount.', async function () { + it('Alice can release 50% of the escrow to Carol for service 6 which includes a referral amount, and fees are correctly split, including referral amount.', async function () { const transactionDetails = await talentLayerEscrow.connect(alice).getTransactionDetails(4) const protocolEscrowFeeRate = transactionDetails.protocolEscrowFeeRate const originServiceFeeRate = transactionDetails.originServiceFeeRate const originValidatedProposalFeeRate = transactionDetails.originValidatedProposalFeeRate const releaseAmount = transactionDetails.amount .add(transactionDetails.releasedAmount) - .mul(BigNumber.from(9)) - .div(BigNumber.from(10)) + .mul(BigNumber.from(1)) + .div(BigNumber.from(2)) const releasedReferrerAmount = releaseAmount .mul(transactionDetails.referralAmount) .div(transactionDetails.amount) @@ -2119,6 +2154,36 @@ describe('TalentLayer protocol global testing', function () { await talentLayerEscrow.connect(deployer).claim(0, ethers.constants.AddressZero) }) + it('Alice can reimburse 40% of the escrow to Carol for service 6 which includes a referral amount.', async function () { + const transactionDetails = await talentLayerEscrow.connect(alice).getTransactionDetails(4) + const protocolEscrowFeeRate = transactionDetails.protocolEscrowFeeRate + const originServiceFeeRate = transactionDetails.originServiceFeeRate + const originValidatedProposalFeeRate = transactionDetails.originValidatedProposalFeeRate + const reimburseAmount = transactionDetails.totalAmount + .mul(BigNumber.from(4)) + .div(BigNumber.from(10)) + + const reimburseReferrerAmount = reimburseAmount + .mul(transactionDetails.referralAmount) + .div(transactionDetails.totalAmount) + const reimburseFeesAMount = reimburseAmount + .mul(protocolEscrowFeeRate) + .add(reimburseAmount.mul(originServiceFeeRate)) + .add(reimburseAmount.mul(originValidatedProposalFeeRate)) + .div(FEE_DIVIDER) + + const totalReimburseAmount = reimburseAmount + .add(reimburseReferrerAmount) + .add(reimburseFeesAMount) + + const tx = await talentLayerEscrow.connect(carol).reimburse(carolTlId, 4, reimburseAmount) + // Alice gets back: 40% of all 3 fees + 40% of referralAmount + await expect(tx).to.changeEtherBalances( + [talentLayerEscrow.address, alice], + [-totalReimburseAmount, totalReimburseAmount], + ) + }) + it('Alice can release the remaining 10% of the escrow (inferior to FEE_DIVIDER value) to Carol, and fees are correctly split, including referral amount.', async function () { const transactionDetails = await talentLayerEscrow.connect(alice).getTransactionDetails(4) const protocolEscrowFeeRate = transactionDetails.protocolEscrowFeeRate @@ -2127,12 +2192,12 @@ describe('TalentLayer protocol global testing', function () { const releaseAmount = transactionDetails.amount const releasedReferrerAmount = releaseAmount .mul(transactionDetails.referralAmount) - .div(transactionDetails.amount.add(transactionDetails.releasedAmount)) + .div(transactionDetails.totalAmount) const transaction = await talentLayerEscrow .connect(alice) .release(aliceTlId, 4, releaseAmount) - // Bob gets half of the referral amount + // Bob gets 10% of the referral amount await expect(transaction).to.changeEtherBalances( [talentLayerEscrow.address, alice, carol, bob], [-releaseAmount.add(releasedReferrerAmount), 0, releaseAmount, releasedReferrerAmount], @@ -2144,7 +2209,7 @@ describe('TalentLayer protocol global testing', function () { const deployerBalance = await talentLayerEscrow .connect(deployer) .getClaimableFeeBalance(ethAddress) - // Alice gets half of both the originServiceFeeRate and the originValidatedProposalFeeRate + // Alice gets 10% of both the originServiceFeeRate and the originValidatedProposalFeeRate expect(alicePlatformBalance).to.be.equal( releaseAmount.mul(originServiceFeeRate + originValidatedProposalFeeRate).div(FEE_DIVIDER), ) @@ -2156,7 +2221,11 @@ describe('TalentLayer protocol global testing', function () { // Service status is finished const serviceData = await talentLayerService.services(transactionDetails.serviceId) + const transactionDetailsAfter = await talentLayerEscrow + .connect(alice) + .getTransactionDetails(4) expect(serviceData.status).to.equal(2) + expect(transactionDetailsAfter.amount).to.equal(0) }) it('Carol should not be allowed to release escrow the service.', async function () { From a7cf3240e56345fae319bd5256aeb717d0b237f9 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Fri, 9 Jun 2023 23:34:46 +0200 Subject: [PATCH 42/99] Remove only Signed-off-by: Quentin D.C --- test/batch/fullWorkflow.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index 3434d42b..a52f71c0 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -34,7 +34,7 @@ const bobPlatformId = 2 const FEE_DIVIDER = 10000 -describe.only('TalentLayer protocol global testing', function () { +describe('TalentLayer protocol global testing', function () { // we define the types of the variables we will use let deployer: SignerWithAddress, alice: SignerWithAddress, From 1110ae365ba9107b3215bd15185063fe15e1b9f2 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Fri, 9 Jun 2023 23:36:52 +0200 Subject: [PATCH 43/99] Reworded Signed-off-by: Quentin D.C --- test/batch/fullWorkflow.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index a52f71c0..a41bcbfb 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -2115,7 +2115,7 @@ describe('TalentLayer protocol global testing', function () { .to.emit(talentLayerEscrow, 'MetaEvidence') }) - it('Alice can release 50% of the escrow to Carol for service 6 which includes a referral amount, and fees are correctly split, including referral amount.', async function () { + it('Alice can release 50% of the escrow to Carol for service 6 which includes a referral amount, and fees are correctly split.', async function () { const transactionDetails = await talentLayerEscrow.connect(alice).getTransactionDetails(4) const protocolEscrowFeeRate = transactionDetails.protocolEscrowFeeRate const originServiceFeeRate = transactionDetails.originServiceFeeRate From 882461b290b9485c5cd021de299c5d5d798ababf Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Mon, 12 Jun 2023 07:14:59 +0200 Subject: [PATCH 44/99] Recatored variables order in Transaction struct Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index 300cf430..1506888a 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -13,7 +13,6 @@ import {ITalentLayerPlatformID} from "./interfaces/ITalentLayerPlatformID.sol"; import "./libs/ERC2771RecipientUpgradeable.sol"; import {IArbitrable} from "./interfaces/IArbitrable.sol"; import {Arbitrator} from "./Arbitrator.sol"; -import "hardhat/console.sol"; /** * @title TalentLayer Escrow Contract @@ -75,7 +74,6 @@ contract TalentLayerEscrow is * @param receiver The intended receiver of the escrow amount * @param token The token used for the transaction * @param amount The amount of the transaction EXCLUDING FEES (will not vary) - * @param amount The amount of the transaction EXCLUDING FEES (will diminish after each release payment) * @param releasedAmount The amount of the transaction that has been released to the receiver EXCLUDING FEES * @param serviceId The ID of the associated service * @param proposalId The id of the validated proposal @@ -92,13 +90,13 @@ contract TalentLayerEscrow is * @param arbitrationFeeTimeout timeout for parties to pay the arbitration fee * @param referrerId the id of the optional referrer * @param referralAmount the optional lump sum optional fee to be sent to the referrer + * @param totalAmount The amount of the transaction EXCLUDING FEES (will diminish after each release payment) */ struct Transaction { uint256 id; address sender; address receiver; address token; - uint256 totalAmount; uint256 amount; uint256 releasedAmount; uint256 serviceId; @@ -116,6 +114,7 @@ contract TalentLayerEscrow is uint256 arbitrationFeeTimeout; uint256 referrerId; uint256 referralAmount; + uint256 totalAmount; } // =========================== Events ============================== From 247371670bb0353d54c5b937b646b91dd42e902a Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Mon, 12 Jun 2023 07:15:17 +0200 Subject: [PATCH 45/99] Updated escrow interface Signed-off-by: Quentin D.C --- contracts/interfaces/ITalentLayerEscrow.sol | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/contracts/interfaces/ITalentLayerEscrow.sol b/contracts/interfaces/ITalentLayerEscrow.sol index b1b56744..0788860c 100644 --- a/contracts/interfaces/ITalentLayerEscrow.sol +++ b/contracts/interfaces/ITalentLayerEscrow.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.9; +import "../Arbitrator.sol"; + /** * @title Platform ID Interface * @author TalentLayer Team | Website: https://talentlayer.org | Twitter: @talentlayer @@ -12,18 +14,23 @@ interface ITalentLayerEscrow { address receiver; address token; uint256 amount; + uint256 releasedAmount; uint256 serviceId; + uint256 proposalId; uint16 protocolEscrowFeeRate; uint16 originServiceFeeRate; uint16 originValidatedProposalFeeRate; + Arbitrator arbitrator; + Status status; uint256 disputeId; uint256 senderFee; uint256 receiverFee; uint256 lastInteraction; - Status status; - // Arbitrator arbitrator; bytes arbitratorExtraData; uint256 arbitrationFeeTimeout; + uint256 referrerId; + uint256 referralAmount; + uint256 totalAmount; } enum Status { From 88049a8c788d704bbd2d4b38113b7b4fa87f3dcb Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Mon, 12 Jun 2023 14:54:43 +0200 Subject: [PATCH 46/99] Update ReferralAmountReleased event Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index 1506888a..1e9d4d37 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -186,10 +186,16 @@ contract TalentLayerEscrow is /** * @notice Emitted after part of a referral amount is released * @param _referrerId The id of the referrer. + * @param _serviceId The related service ID. * @param _token The address of the token used for the payment. * @param _amount The amount released. */ - event ReferralAmountReleased(uint256 indexed _referrerId, address indexed _token, uint256 _amount); + event ReferralAmountReleased( + uint256 indexed _referrerId, + uint256 _serviceId, + address indexed _token, + uint256 _amount + ); /** * @notice Emitted when a party has to pay a fee for the dispute or would otherwise be considered as losing. @@ -477,10 +483,11 @@ contract TalentLayerEscrow is ? talentLayerPlatformIdContract.getPlatform(proposal.platformId) : originServiceCreationPlatform; - // uint256 referralAmount = service.referralAmount; - // if (transaction.referrer == address(0)) { - // referralAmount = 0; - // } + //TODO check if this is needed + uint256 referralAmount = service.referralAmount; + if (proposal.referrerId == 0) { + referralAmount = 0; + } uint256 transactionAmount = _calculateTotalWithFees( proposal.rateAmount, @@ -987,7 +994,12 @@ contract TalentLayerEscrow is originServiceFeeRate ); - emit ReferralAmountReleased(transaction.referrerId, transaction.token, releasedReferralAmount); + emit ReferralAmountReleased( + transaction.referrerId, + transaction.serviceId, + transaction.token, + releasedReferralAmount + ); } /** From 8015bb86d47b755b7e4221515ecb866a07477ae7 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Tue, 13 Jun 2023 15:03:21 +0200 Subject: [PATCH 47/99] Updated Service Interface Signed-off-by: Quentin D.C --- contracts/interfaces/ITalentLayerService.sol | 43 +++++++++++++++++--- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/contracts/interfaces/ITalentLayerService.sol b/contracts/interfaces/ITalentLayerService.sol index ef14a14c..77faf8de 100644 --- a/contracts/interfaces/ITalentLayerService.sol +++ b/contracts/interfaces/ITalentLayerService.sol @@ -55,27 +55,58 @@ interface ITalentLayerService { uint256 _tokenId, uint256 _platformId, uint256 _ownerId, - string calldata _dataUri + string calldata _dataUri, + address _token + ) external returns (uint256); + + function createServiceWithReferral( + uint256 _profileId, + uint256 _platformId, + string calldata _dataUri, + bytes calldata _signature, + address _token, + uint256 _referralAmount ) external returns (uint256); function createProposal( + uint256 _profileId, uint256 _serviceId, - address _rateToken, uint256 _rateAmount, uint256 _platformId, - string calldata _dataUri + string calldata _dataUri, + uint256 _expirationDate, + bytes calldata _signature + ) external; + + function createProposalWithReferrer( + uint256 _profileId, + uint256 _serviceId, + uint256 _rateAmount, + uint256 _platformId, + string calldata _dataUri, + uint256 _expirationDate, + bytes calldata _signature, + uint256 _referrerId ) external; function afterDeposit(uint256 _serviceId, uint256 _proposalId, uint256 _transactionId) external; function updateProposal( + uint256 _profileId, uint256 _serviceId, - address _rateToken, uint256 _rateAmount, - string calldata _dataUri + string calldata _dataUri, + uint256 _expirationDate, + uint256 _referrerId ) external; function afterFullPayment(uint256 _serviceId, uint256 _releasedAmount) external; - function updateServiceData(uint256 _serviceId, string calldata _dataUri) external; + function updateService( + uint256 _profileId, + uint256 _serviceId, + uint256 _referralAmount, + address _token, + string calldata _dataUri + ) external; } From dd0d1a7c786ff520a69f11c7c641864dc4cdae6a Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Tue, 13 Jun 2023 15:06:54 +0200 Subject: [PATCH 48/99] Refactored Escrow contract: last version Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index 1e9d4d37..771ea2f7 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -483,7 +483,6 @@ contract TalentLayerEscrow is ? talentLayerPlatformIdContract.getPlatform(proposal.platformId) : originServiceCreationPlatform; - //TODO check if this is needed uint256 referralAmount = service.referralAmount; if (proposal.referrerId == 0) { referralAmount = 0; @@ -968,16 +967,20 @@ contract TalentLayerEscrow is transaction.token ] += originValidatedProposalFeeRate; - uint256 releasedReferralAmount = 0; - - //TODO can amount be 0? Not as long as min amount in service contract - if (transaction.referrerId != 0) { - releasedReferralAmount = (_releaseAmount * transaction.referralAmount) / (transaction.totalAmount); + if (transaction.referrerId != 0 && transaction.referralAmount != 0) { + uint256 releasedReferralAmount = (_releaseAmount * transaction.referralAmount) / (transaction.totalAmount); _safeTransferBalance( payable(talentLayerIdContract.ownerOf(transaction.referrerId)), transaction.token, releasedReferralAmount ); + + emit ReferralAmountReleased( + transaction.referrerId, + transaction.serviceId, + transaction.token, + releasedReferralAmount + ); } emit OriginServiceFeeRateReleased( @@ -993,13 +996,6 @@ contract TalentLayerEscrow is transaction.token, originServiceFeeRate ); - - emit ReferralAmountReleased( - transaction.referrerId, - transaction.serviceId, - transaction.token, - releasedReferralAmount - ); } /** From 21543e71e57bdf7c739ae976616d8294fef2f5ef Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Tue, 13 Jun 2023 15:14:22 +0200 Subject: [PATCH 49/99] Small gas optimization Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index 771ea2f7..e1327028 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -925,7 +925,7 @@ contract TalentLayerEscrow is */ function _reimburse(uint256 _transactionId, uint256 _amount) private { Transaction storage transaction = transactions[_transactionId]; - uint256 reimbursedReferralAmount = 0; + uint256 reimbursedReferralAmount; if (transaction.referrerId != 0) { reimbursedReferralAmount = (_amount * transaction.referralAmount) / (transaction.totalAmount); From 1fe877b457047b4cd655b9dfb4b93b5124339246 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Tue, 13 Jun 2023 15:50:53 +0200 Subject: [PATCH 50/99] Added require statement + 2 pending features Signed-off-by: Quentin D.C --- contracts/TalentLayerService.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contracts/TalentLayerService.sol b/contracts/TalentLayerService.sol index 442870ed..fe6e6db8 100644 --- a/contracts/TalentLayerService.sol +++ b/contracts/TalentLayerService.sol @@ -420,6 +420,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU address _token, uint256 _referralAmount ) public payable onlyOwnerOrDelegate(_profileId) returns (uint256) { + require(_referralAmount > 0, "Referral amount must be greater than 0"); _validateService(_profileId, _platformId, _dataUri, _signature, _token); uint256 id = nextServiceId; @@ -518,6 +519,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU proposals[_serviceId][_profileId] = Proposal({ status: ProposalStatus.Pending, ownerId: _profileId, + //TODO keep address 0 ar add service token address ? (Need get Service if so) rateToken: address(0), rateAmount: _rateAmount, platformId: _platformId, @@ -772,6 +774,8 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU require(service.status == Status.Opened, "Service not opened"); require(service.ownerId != 0, "Service not exist"); require(proposals[_serviceId][_profileId].ownerId != _profileId, "proposal already exist"); + //TODO check to do this ? + // require(service.referralAmount > 0, "Can't refer someone for this service"); require(service.ownerId != _profileId, "can't create for your own service"); require(bytes(_dataUri).length == 46, "Invalid cid"); From 95ce758c572a1291cb3a2a3bf80d33eeb6a3506a Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 14 Jun 2023 16:19:20 +0200 Subject: [PATCH 51/99] Modified comments Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index e1327028..ce710542 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -73,7 +73,7 @@ contract TalentLayerEscrow is * @param sender The party paying the escrow amount * @param receiver The intended receiver of the escrow amount * @param token The token used for the transaction - * @param amount The amount of the transaction EXCLUDING FEES (will not vary) + * @param amount The amount of the transaction EXCLUDING FEES (will diminish after each release payment) * @param releasedAmount The amount of the transaction that has been released to the receiver EXCLUDING FEES * @param serviceId The ID of the associated service * @param proposalId The id of the validated proposal @@ -90,7 +90,7 @@ contract TalentLayerEscrow is * @param arbitrationFeeTimeout timeout for parties to pay the arbitration fee * @param referrerId the id of the optional referrer * @param referralAmount the optional lump sum optional fee to be sent to the referrer - * @param totalAmount The amount of the transaction EXCLUDING FEES (will diminish after each release payment) + * @param totalAmount The amount of the transaction EXCLUDING FEES (will not vary) */ struct Transaction { uint256 id; From 7494ba118ded308c141f6207cee5a578d570eb83 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 14 Jun 2023 16:19:49 +0200 Subject: [PATCH 52/99] Removed createServiceWithReferral function & event Signed-off-by: Quentin D.C --- contracts/TalentLayerService.sol | 53 ++------------------------------ 1 file changed, 3 insertions(+), 50 deletions(-) diff --git a/contracts/TalentLayerService.sol b/contracts/TalentLayerService.sol index fe6e6db8..ca02cd10 100644 --- a/contracts/TalentLayerService.sol +++ b/contracts/TalentLayerService.sol @@ -93,15 +93,6 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU // =========================== Events ============================== - /** - * @notice Emitted after a new service is created - * @param id The service ID (incremental) - * @param ownerId the talentLayerId of the buyer - * @param platformId platform ID on which the Service token was minted - * @param dataUri token Id to IPFS URI mapping - */ - event ServiceCreated(uint256 id, uint256 ownerId, uint256 platformId, string dataUri); - /** * @notice Emitted after a new service is created with referral data * @param id The service ID (incremental) @@ -111,7 +102,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param token the token used for the service's payments, including the referral amount * @param referralAmount the amount which the referrer will receive if a proposal is validated by un user which was referred */ - event ServiceCreatedWithReferral( + event ServiceCreated( uint256 indexed id, uint256 ownerId, uint256 platformId, @@ -373,46 +364,9 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param _dataUri IPFS URI of the offchain data of the service * @param _signature optional platform signature to allow the operation * @param _token token address to be used for the service's payments - */ - function createService( - uint256 _profileId, - uint256 _platformId, - string calldata _dataUri, - bytes calldata _signature, - address _token - ) public payable onlyOwnerOrDelegate(_profileId) returns (uint256) { - _validateService(_profileId, _platformId, _dataUri, _signature, _token); - - uint256 id = nextServiceId; - nextServiceId++; - - Service storage service = services[id]; - service.status = Status.Opened; - service.ownerId = _profileId; - service.dataUri = _dataUri; - service.platformId = _platformId; - service.token = _token; - - if (serviceNonce[_profileId] == 0 && proposalNonce[_profileId] == 0) { - tlId.setHasActivity(_profileId); - } - serviceNonce[_profileId]++; - - emit ServiceCreated(id, _profileId, _platformId, _dataUri); - - return id; - } - - /** - * @notice Allows a buyer to initiate an open service - * @param _profileId The TalentLayer ID of the user owner of the service - * @param _platformId platform ID on which the Service token was created - * @param _dataUri IPFS URI of the offchain data of the service - * @param _signature optional platform signature to allow the operation - * @param _token the token used for the referral amount * @param _referralAmount the amount which the referrer will receive if a proposal is validated by un user which was referred */ - function createServiceWithReferral( + function createService( uint256 _profileId, uint256 _platformId, string calldata _dataUri, @@ -420,7 +374,6 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU address _token, uint256 _referralAmount ) public payable onlyOwnerOrDelegate(_profileId) returns (uint256) { - require(_referralAmount > 0, "Referral amount must be greater than 0"); _validateService(_profileId, _platformId, _dataUri, _signature, _token); uint256 id = nextServiceId; @@ -439,7 +392,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU } serviceNonce[_profileId]++; - emit ServiceCreatedWithReferral(id, _profileId, _platformId, _dataUri, _token, _referralAmount); + emit ServiceCreated(id, _profileId, _platformId, _dataUri, _token, _referralAmount); return id; } From 6906e6ff794fba7b6eb3f0e5e10f9412570e12e7 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 14 Jun 2023 16:20:17 +0200 Subject: [PATCH 53/99] Updated tests Signed-off-by: Quentin D.C --- test/batch/delegationSystem.ts | 6 +-- test/batch/disputeResolution.ts | 2 +- test/batch/fullWorkflow.ts | 77 +++++++++++++++--------------- test/batch/pausableEscrow.ts | 2 +- test/batch/platformVerification.ts | 14 +++--- test/batch/serviceCompletion.ts | 2 +- test/batch/transferProfileIds.ts | 2 +- 7 files changed, 53 insertions(+), 52 deletions(-) diff --git a/test/batch/delegationSystem.ts b/test/batch/delegationSystem.ts index 47c995e8..c7ce4e14 100644 --- a/test/batch/delegationSystem.ts +++ b/test/batch/delegationSystem.ts @@ -132,12 +132,12 @@ describe('Delegation System', function () { const signature = await getSignatureForService(platformOneOwner, aliceTlId, 0, cid) const tx = talentLayerService .connect(eve) - .createService(aliceTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero) + .createService(aliceTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero, 0) await expect(tx).to.be.revertedWith('Not owner or delegate') await talentLayerService .connect(dave) - .createService(aliceTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero) + .createService(aliceTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero, 0) const serviceData = await talentLayerService.services(1) expect(serviceData.ownerId.toNumber()).to.be.equal(aliceTlId) @@ -241,7 +241,7 @@ describe('Delegation System', function () { const signature = await getSignatureForService(platformOneOwner, aliceTlId, 1, cid) const tx = talentLayerService .connect(dave) - .createService(aliceTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero) + .createService(aliceTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero, 0) await expect(tx).to.be.revertedWith('Not owner or delegate') }) }) diff --git a/test/batch/disputeResolution.ts b/test/batch/disputeResolution.ts index dba303c0..b3526e39 100644 --- a/test/batch/disputeResolution.ts +++ b/test/batch/disputeResolution.ts @@ -101,7 +101,7 @@ async function deployAndSetup( const signature = await getSignatureForService(carol, aliceTlId, 0, cid) await talentLayerService .connect(alice) - .createService(aliceTlId, carolPlatformId, cid, signature, tokenAddress) + .createService(aliceTlId, carolPlatformId, cid, signature, tokenAddress, 0) // Bob, the seller, creates a proposal for the service const signature2 = await getSignatureForProposal(carol, bobTlId, serviceId, cid) diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index a41bcbfb..75304d7c 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -745,7 +745,7 @@ describe('TalentLayer protocol global testing', function () { await expect( talentLayerService .connect(dave) - .createService(0, 1, 'haveNotTlid', signature, token.address), + .createService(0, 1, 'haveNotTlid', signature, token.address, 0), ).to.be.revertedWith('ERC721: invalid token ID') }) @@ -754,7 +754,7 @@ describe('TalentLayer protocol global testing', function () { await expect( talentLayerService .connect(alice) - .createService(aliceTlId, 0, cid, signature, token.address), + .createService(aliceTlId, 0, cid, signature, token.address, 0), ).to.be.revertedWith('Invalid platform ID') }) @@ -765,7 +765,7 @@ describe('TalentLayer protocol global testing', function () { const signature = await getSignatureForService(platformOneOwner, aliceTlId, 0, cid) const tx = talentLayerService .connect(alice) - .createService(aliceTlId, alicePlatformId, cid, signature, token.address, { + .createService(aliceTlId, alicePlatformId, cid, signature, token.address, 0, { value: alicePlatformServicePostingFee.sub(1), }) @@ -779,7 +779,7 @@ describe('TalentLayer protocol global testing', function () { const signature = await getSignatureForService(platformOneOwner, aliceTlId, 0, cid) const tx = talentLayerService .connect(alice) - .createService(aliceTlId, alicePlatformId, cid, signature, nonListedRateToken, { + .createService(aliceTlId, alicePlatformId, cid, signature, nonListedRateToken, 0, { value: alicePlatformServicePostingFee, }) @@ -794,7 +794,7 @@ describe('TalentLayer protocol global testing', function () { const signature = await getSignatureForService(platformOneOwner, aliceTlId, 0, cid) await talentLayerService .connect(alice) - .createService(aliceTlId, alicePlatformId, cid, signature, token.address, { + .createService(aliceTlId, alicePlatformId, cid, signature, token.address, 0, { value: alicePlatformServicePostingFee, }) const service1Data = await talentLayerService.services(1) @@ -803,7 +803,7 @@ describe('TalentLayer protocol global testing', function () { const signature2 = await getSignatureForService(platformOneOwner, aliceTlId, 1, cid) await talentLayerService .connect(alice) - .createService(aliceTlId, alicePlatformId, cid, signature2, token.address, { + .createService(aliceTlId, alicePlatformId, cid, signature2, token.address, 0, { value: alicePlatformServicePostingFee, }) await talentLayerService.services(2) @@ -812,16 +812,24 @@ describe('TalentLayer protocol global testing', function () { const signature3 = await getSignatureForService(platformOneOwner, aliceTlId, 2, cid) await talentLayerService .connect(alice) - .createService(aliceTlId, alicePlatformId, cid, signature3, ethers.constants.AddressZero, { - value: alicePlatformServicePostingFee, - }) + .createService( + aliceTlId, + alicePlatformId, + cid, + signature3, + ethers.constants.AddressZero, + 0, + { + value: alicePlatformServicePostingFee, + }, + ) await talentLayerService.services(3) // service 4 const signature4 = await getSignatureForService(platformOneOwner, aliceTlId, 3, cid) await talentLayerService .connect(alice) - .createService(aliceTlId, alicePlatformId, cid, signature4, token.address, { + .createService(aliceTlId, alicePlatformId, cid, signature4, token.address, 0, { value: alicePlatformServicePostingFee, }) await talentLayerService.services(4) @@ -830,7 +838,7 @@ describe('TalentLayer protocol global testing', function () { const signature5 = await getSignatureForService(platformOneOwner, aliceTlId, 4, cid) await talentLayerService .connect(alice) - .createService(aliceTlId, alicePlatformId, cid, signature5, token.address, { + .createService(aliceTlId, alicePlatformId, cid, signature5, token.address, 0, { value: alicePlatformServicePostingFee, }) await talentLayerService.services(5) @@ -847,22 +855,23 @@ describe('TalentLayer protocol global testing', function () { const alicePlatformServicePostingFee = platform.servicePostingFee const signature = await getSignatureForService(platformOneOwner, aliceTlId, 5, cid) - const tx = await talentLayerService.connect(alice).createServiceWithReferral( - aliceTlId, - alicePlatformId, - cid, - signature, - ethers.constants.AddressZero, - // token.address, - referralAmount, - { - value: alicePlatformServicePostingFee, - }, - ) + const tx = await talentLayerService + .connect(alice) + .createService( + aliceTlId, + alicePlatformId, + cid, + signature, + ethers.constants.AddressZero, + referralAmount, + { + value: alicePlatformServicePostingFee, + }, + ) const service6Data = await talentLayerService.services(6) expect(tx) - .to.emit(talentLayerService, 'ServiceCreatedWithReferral') + .to.emit(talentLayerService, 'ServiceCreated') .withArgs(6, aliceTlId, alicePlatformId, cid, token.address, referralAmount) expect(service6Data.status).to.be.equal(ServiceStatus.Opened) @@ -880,21 +889,13 @@ describe('TalentLayer protocol global testing', function () { const signature = await getSignatureForService(platformOneOwner, aliceTlId, 6, cid) const tx = await talentLayerService .connect(alice) - .createServiceWithReferral( - aliceTlId, - alicePlatformId, - cid, - signature, - token.address, - referralAmount, - { - value: alicePlatformServicePostingFee, - }, - ) + .createService(aliceTlId, alicePlatformId, cid, signature, token.address, referralAmount, { + value: alicePlatformServicePostingFee, + }) const service7Data = await talentLayerService.services(7) expect(tx) - .to.emit(talentLayerService, 'ServiceCreatedWithReferral') + .to.emit(talentLayerService, 'ServiceCreated') .withArgs(7, aliceTlId, alicePlatformId, cid, token.address, referralAmount) expect(service7Data.status).to.be.equal(ServiceStatus.Opened) @@ -910,7 +911,7 @@ describe('TalentLayer protocol global testing', function () { await expect( talentLayerService .connect(alice) - .createService(aliceTlId, 5, 'wrongTlPid', signature, token.address), + .createService(aliceTlId, 5, 'wrongTlPid', signature, token.address, 0), ).to.be.revertedWith('Invalid platform ID') }) @@ -1797,7 +1798,7 @@ describe('TalentLayer protocol global testing', function () { const signature = await getSignatureForService(platformOneOwner, aliceTlId, 5, cid) await talentLayerService .connect(alice) - .createService(aliceTlId, 1, cid, signature, token.address, { + .createService(aliceTlId, 1, cid, signature, token.address, 0, { value: alicePlatformServicePostingFee, }) await talentLayerService.services(serviceId) diff --git a/test/batch/pausableEscrow.ts b/test/batch/pausableEscrow.ts index fe69e540..3b3da14c 100644 --- a/test/batch/pausableEscrow.ts +++ b/test/batch/pausableEscrow.ts @@ -70,7 +70,7 @@ async function deployAndSetup(): Promise< const signature = await getSignatureForService(carol, aliceTlId, 0, cid) await talentLayerService .connect(alice) - .createService(aliceTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero) + .createService(aliceTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero, 0) // Bob, the seller, creates a proposal for the service const signature2 = await getSignatureForProposal(carol, bobTlId, serviceId, cid) diff --git a/test/batch/platformVerification.ts b/test/batch/platformVerification.ts index c07a3c89..57bc6072 100644 --- a/test/batch/platformVerification.ts +++ b/test/batch/platformVerification.ts @@ -119,7 +119,7 @@ describe('Platform verification', function () { const tx = talentLayerService .connect(alice) - .createService(aliceTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero) + .createService(aliceTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero, 0) await expect(tx).to.not.reverted }) @@ -129,7 +129,7 @@ describe('Platform verification', function () { const tx = talentLayerService .connect(bob) - .createService(bobTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero) + .createService(bobTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero, 0) await expect(tx).to.revertedWith('invalid signature') }) @@ -139,7 +139,7 @@ describe('Platform verification', function () { const tx = talentLayerService .connect(bob) - .createService(bobTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero) + .createService(bobTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero, 0) await expect(tx).to.revertedWith('invalid signature') }) @@ -149,7 +149,7 @@ describe('Platform verification', function () { const tx = talentLayerService .connect(bob) - .createService(bobTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero) + .createService(bobTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero, 0) await expect(tx).to.revertedWith('invalid signature') }) @@ -159,7 +159,7 @@ describe('Platform verification', function () { const tx = talentLayerService .connect(alice) - .createService(aliceTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero) + .createService(aliceTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero, 0) await expect(tx).to.revertedWith('invalid signature') }) @@ -169,7 +169,7 @@ describe('Platform verification', function () { const tx = talentLayerService .connect(alice) - .createService(aliceTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero) + .createService(aliceTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero, 0) await expect(tx).to.not.reverted }) @@ -208,7 +208,7 @@ describe('Platform verification', function () { const tx = await talentLayerService .connect(alice) - .createService(aliceTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero) + .createService(aliceTlId, carolPlatformId, cid, signature, ethers.constants.AddressZero, 0) await expect(tx).to.not.reverted }) diff --git a/test/batch/serviceCompletion.ts b/test/batch/serviceCompletion.ts index 2b4823c1..c5b79788 100644 --- a/test/batch/serviceCompletion.ts +++ b/test/batch/serviceCompletion.ts @@ -129,7 +129,7 @@ describe('Completion of service', function () { ) await talentLayerService .connect(alice) - .createService(aliceTlId, carolPlatformId, cid, signatureService, tokenAddress) + .createService(aliceTlId, carolPlatformId, cid, signatureService, tokenAddress, 0) // Bob, the seller, creates a proposal for the service const signatureProposal = await getSignatureForProposal(carol, bobTlId, serviceId, cid) diff --git a/test/batch/transferProfileIds.ts b/test/batch/transferProfileIds.ts index 19677893..cc03e3f3 100644 --- a/test/batch/transferProfileIds.ts +++ b/test/batch/transferProfileIds.ts @@ -94,7 +94,7 @@ describe('Transfer of TalentLayer IDs', function () { const signature = await getSignatureForService(eve, bobTlId.toNumber(), 0, cid) await talentLayerService .connect(bob) - .createService(bobTlId, evePlatformId, cid, signature, tokenAddress) + .createService(bobTlId, evePlatformId, cid, signature, tokenAddress, 0) expect(await talentLayerID.hasActivity(bobTlId)).to.be.true From 3b36de52e513a4e4b94a2d39e7deafd5894996bf Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 14 Jun 2023 19:17:34 +0200 Subject: [PATCH 54/99] Removed token from service update Added requirement on referralAmount Signed-off-by: Quentin D.C --- contracts/TalentLayerService.sol | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/contracts/TalentLayerService.sol b/contracts/TalentLayerService.sol index ca02cd10..550d3a4c 100644 --- a/contracts/TalentLayerService.sol +++ b/contracts/TalentLayerService.sol @@ -129,9 +129,8 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param id The service ID * @param dataUri New service Data URI * @param referralAmount New referral amount - * @param token New service token */ - event ServiceUpdated(uint256 indexed id, string dataUri, uint256 referralAmount, address token); + event ServiceUpdated(uint256 indexed id, string dataUri, uint256 referralAmount); /** * @notice Emitted after a new proposal is created @@ -598,27 +597,24 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param _profileId The TalentLayer ID of the user, owner of the service * @param _serviceId, Service ID to update * @param _referralAmount, New referral amount - * @param _token, New token address * @param _dataUri New IPFS URI */ function updateService( uint256 _profileId, uint256 _serviceId, uint256 _referralAmount, - address _token, string calldata _dataUri ) public onlyOwnerOrDelegate(_profileId) { Service storage service = services[_serviceId]; require(service.ownerId == _profileId, "Not the owner"); require(service.status == Status.Opened, "status must be opened"); - require(allowedTokenList[_token].isWhitelisted, "Token not allowed"); require(bytes(_dataUri).length == 46, "Invalid cid"); + require(_referralAmount >= service.referralAmount, "Can't reduce referral amount"); service.dataUri = _dataUri; service.referralAmount = _referralAmount; - service.token = _token; - emit ServiceUpdated(_serviceId, _dataUri, _referralAmount, _token); + emit ServiceUpdated(_serviceId, _dataUri, _referralAmount); } /** From c4bb7857d4f24c769dc454ebc4ce706ce1f76d8b Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 14 Jun 2023 19:18:07 +0200 Subject: [PATCH 55/99] Updated tests Signed-off-by: Quentin D.C --- test/batch/delegationSystem.ts | 4 +--- test/batch/fullWorkflow.ts | 17 ++++++----------- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/test/batch/delegationSystem.ts b/test/batch/delegationSystem.ts index c7ce4e14..3c03d6eb 100644 --- a/test/batch/delegationSystem.ts +++ b/test/batch/delegationSystem.ts @@ -144,9 +144,7 @@ describe('Delegation System', function () { }) it('Dave can update service data on behalf of Alice', async function () { - const tx = await talentLayerService - .connect(dave) - .updateService(aliceTlId, serviceId, referralAmount, ethers.constants.AddressZero, cid) + const tx = await talentLayerService.connect(dave).updateService(aliceTlId, serviceId, 0, cid) await expect(tx).to.not.be.reverted }) diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index 75304d7c..dc0588c3 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -916,31 +916,26 @@ describe('TalentLayer protocol global testing', function () { }) it('Alice can update her service data', async function () { - await talentLayerService - .connect(alice) - .updateService(aliceTlId, 1, referralAmount, token.address, cid2) + await talentLayerService.connect(alice).updateService(aliceTlId, 1, referralAmount, cid2) const serviceData = await talentLayerService.services(1) expect(serviceData.dataUri).to.be.equal(cid2) const newReferralAmount = 40000 const tx = await talentLayerService .connect(alice) - .updateService(aliceTlId, 6, newReferralAmount, ethers.constants.AddressZero, cid2) + .updateService(aliceTlId, 6, newReferralAmount, cid2) const service6Data = await talentLayerService.services(6) expect(tx) .to.emit(talentLayerService, 'ServiceUpdated') .withArgs(6, cid2, newReferralAmount, ethers.constants.AddressZero) expect(service6Data.referralAmount).to.be.equal(newReferralAmount) - expect(service6Data.token).to.be.equal(ethers.constants.AddressZero) }) - it('Alice cannot update her service with a non-whitelisted token', async function () { + it('Alice cannot update her service with an inferior referral amount', async function () { await expect( - talentLayerService - .connect(alice) - .updateService(aliceTlId, 1, referralAmount, nonListedRateToken, cid2), - ).to.be.revertedWith('Token not allowed') + talentLayerService.connect(alice).updateService(aliceTlId, 1, referralAmount - 1, cid2), + ).to.be.revertedWith("Can't reduce referral amount") }) it('Alice can cancel her own service', async function () { @@ -1464,7 +1459,7 @@ describe('TalentLayer protocol global testing', function () { it('Alice cannot update her service data after it is confirmed', async function () { const tx = talentLayerService .connect(alice) - .updateService(aliceTlId, serviceId, referralAmount, token.address, cid2) + .updateService(aliceTlId, serviceId, referralAmount, cid2) await expect(tx).to.be.revertedWith('status must be opened') }) From f805f959f7d7becc2178618469fbf782f44711db Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 14 Jun 2023 19:50:35 +0200 Subject: [PATCH 56/99] Removed createProposalWithReferrer Signed-off-by: Quentin D.C --- contracts/TalentLayerService.sol | 81 ++------------------------------ 1 file changed, 5 insertions(+), 76 deletions(-) diff --git a/contracts/TalentLayerService.sol b/contracts/TalentLayerService.sol index 550d3a4c..76bbc925 100644 --- a/contracts/TalentLayerService.sol +++ b/contracts/TalentLayerService.sol @@ -132,28 +132,6 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU */ event ServiceUpdated(uint256 indexed id, string dataUri, uint256 referralAmount); - /** - * @notice Emitted after a new proposal is created - * @param serviceId The service id - * @param ownerId The talentLayerId of the seller who made the proposal - * @param dataUri token Id to IPFS URI mapping - * @param status proposal status - * @param rateToken the token choose for the payment - * @param rateAmount the amount of token chosen - * @param platformId the platform ID on which the proposal was created - * @param expirationDate the timeout for the proposal - */ - event ProposalCreated( - uint256 serviceId, - uint256 ownerId, - string dataUri, - ProposalStatus status, - address rateToken, - uint256 rateAmount, - uint256 platformId, - uint256 expirationDate - ); - /** * @notice Emitted after a new proposal is created * @param serviceId The service id @@ -165,7 +143,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param expirationDate the timeout for the proposal * @param referrerId the id of the referrer (Zero if no referrer) */ - event ProposalCreatedWithoutToken( + event ProposalCreated( uint256 serviceId, uint256 ownerId, string dataUri, @@ -396,55 +374,6 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU return id; } - /** - * @notice Allows an seller to propose his service for a service - * @param _profileId The TalentLayer ID of the user owner of the proposal - * @param _serviceId The service linked to the new proposal - * @param _rateAmount the amount of token chosen - * @param _dataUri token Id to IPFS URI mapping - * @param _platformId platform ID from where the proposal is created - * @param _expirationDate the time before the proposal is automatically validated - * @param _signature optional platform signature to allow the operation - */ - function createProposal( - uint256 _profileId, - uint256 _serviceId, - uint256 _rateAmount, - uint256 _platformId, - string calldata _dataUri, - uint256 _expirationDate, - bytes calldata _signature - ) public payable onlyOwnerOrDelegate(_profileId) { - _validateProposal(_profileId, _serviceId, _rateAmount, _platformId, _dataUri, _signature, 0); - - proposals[_serviceId][_profileId] = Proposal({ - status: ProposalStatus.Pending, - ownerId: _profileId, - rateToken: address(0), - rateAmount: _rateAmount, - platformId: _platformId, - dataUri: _dataUri, - expirationDate: _expirationDate, - referrerId: 0 - }); - - if (serviceNonce[_profileId] == 0 && proposalNonce[_profileId] == 0) { - tlId.setHasActivity(_profileId); - } - proposalNonce[_profileId]++; - - emit ProposalCreatedWithoutToken( - _serviceId, - _profileId, - _dataUri, - ProposalStatus.Pending, - _rateAmount, - _platformId, - _expirationDate, - 0 - ); - } - /** * @notice Allows an seller to propose his service for a service * @param _profileId The TalentLayer ID of the user owner of the proposal @@ -456,7 +385,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param _signature optional platform signature to allow the operation * @param _referrerId the id of the referrer (Zero if no referrer) */ - function createProposalWithReferrer( + function createProposal( uint256 _profileId, uint256 _serviceId, uint256 _rateAmount, @@ -466,13 +395,13 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU bytes calldata _signature, uint256 _referrerId ) public payable onlyOwnerOrDelegate(_profileId) { + Service storage service = services[_serviceId]; _validateProposal(_profileId, _serviceId, _rateAmount, _platformId, _dataUri, _signature, _referrerId); proposals[_serviceId][_profileId] = Proposal({ status: ProposalStatus.Pending, ownerId: _profileId, - //TODO keep address 0 ar add service token address ? (Need get Service if so) - rateToken: address(0), + rateToken: service.token, rateAmount: _rateAmount, platformId: _platformId, dataUri: _dataUri, @@ -485,7 +414,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU } proposalNonce[_profileId]++; - emit ProposalCreatedWithoutToken( + emit ProposalCreated( _serviceId, _profileId, _dataUri, From 9330f92637dd47ae49530969fc8db11633b858f9 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 14 Jun 2023 19:51:08 +0200 Subject: [PATCH 57/99] Updated tests Signed-off-by: Quentin D.C --- test/batch/delegationSystem.ts | 1 + test/batch/disputeResolution.ts | 1 + test/batch/fullWorkflow.ts | 123 ++++++++++++++++++++++------- test/batch/pausableEscrow.ts | 1 + test/batch/platformVerification.ts | 2 + test/batch/serviceCompletion.ts | 1 + test/batch/transferProfileIds.ts | 1 + 7 files changed, 103 insertions(+), 27 deletions(-) diff --git a/test/batch/delegationSystem.ts b/test/batch/delegationSystem.ts index 3c03d6eb..1ec120ef 100644 --- a/test/batch/delegationSystem.ts +++ b/test/batch/delegationSystem.ts @@ -160,6 +160,7 @@ describe('Delegation System', function () { cid, proposalExpirationDate, signature, + 0, ) const proposal = await talentLayerService.proposals(serviceId, bobTlId) expect(proposal.ownerId).to.eq(bobTlId) diff --git a/test/batch/disputeResolution.ts b/test/batch/disputeResolution.ts index b3526e39..640183c2 100644 --- a/test/batch/disputeResolution.ts +++ b/test/batch/disputeResolution.ts @@ -115,6 +115,7 @@ async function deployAndSetup( cid, proposalExpirationDate, signature2, + 0, ) return [talentLayerPlatformID, talentLayerEscrow, talentLayerArbitrator, talentLayerService] diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index dc0588c3..1b16dcc3 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -957,9 +957,19 @@ describe('TalentLayer protocol global testing', function () { const signature = await getSignatureForProposal(platformOneOwner, aliceTlId, 1, cid) const tx = talentLayerService .connect(alice) - .createProposal(aliceTlId, 1, 15, alicePlatformId, cid, proposalExpirationDate, signature, { - value: alicePlatformProposalPostingFee, - }) + .createProposal( + aliceTlId, + 1, + 15, + alicePlatformId, + cid, + proposalExpirationDate, + signature, + 0, + { + value: alicePlatformProposalPostingFee, + }, + ) await expect(tx).to.be.revertedWith("can't create for your own service") }) @@ -971,7 +981,7 @@ describe('TalentLayer protocol global testing', function () { await expect( talentLayerService .connect(bob) - .createProposal(bobTlId, 5, 15, bobPlatformId, cid, proposalExpirationDate, signature), + .createProposal(bobTlId, 5, 15, bobPlatformId, cid, proposalExpirationDate, signature, 0), ).to.be.revertedWith('Service not opened') }) @@ -999,9 +1009,19 @@ describe('TalentLayer protocol global testing', function () { await expect( talentLayerService .connect(bob) - .createProposal(bobTlId, 1, 9, alicePlatformId, cid, proposalExpirationDate, signature, { - value: alicePlatformProposalPostingFee, - }), + .createProposal( + bobTlId, + 1, + 9, + alicePlatformId, + cid, + proposalExpirationDate, + signature, + 0, + { + value: alicePlatformProposalPostingFee, + }, + ), ).to.be.revertedWith('Amount too low') }) @@ -1013,9 +1033,19 @@ describe('TalentLayer protocol global testing', function () { const signature = await getSignatureForProposal(platformOneOwner, bobTlId, 1, cid2) const tx = talentLayerService .connect(bob) - .createProposal(bobTlId, 1, 15, alicePlatformId, cid2, proposalExpirationDate, signature, { - value: alicePlatformProposalPostingFee.sub(1), - }) + .createProposal( + bobTlId, + 1, + 15, + alicePlatformId, + cid2, + proposalExpirationDate, + signature, + 0, + { + value: alicePlatformProposalPostingFee.sub(1), + }, + ) await expect(tx).to.be.revertedWith('Non-matching funds') }) @@ -1034,9 +1064,19 @@ describe('TalentLayer protocol global testing', function () { const signature = await getSignatureForProposal(platformOneOwner, bobTlId, 1, cid2) const tx = await talentLayerService .connect(bob) - .createProposal(bobTlId, 1, 15, alicePlatformId, cid2, proposalExpirationDate, signature, { - value: alicePlatformProposalPostingFee, - }) + .createProposal( + bobTlId, + 1, + 15, + alicePlatformId, + cid2, + proposalExpirationDate, + signature, + 0, + { + value: alicePlatformProposalPostingFee, + }, + ) const serviceData = await talentLayerService.services(1) const proposalDataAfter = await talentLayerService.getProposal(1, bobTid) @@ -1047,7 +1087,7 @@ describe('TalentLayer protocol global testing', function () { // Proposal data check after the proposal // @dev: rateToken field not used any more - expect(proposalDataAfter.rateToken).to.be.equal(ethers.constants.AddressZero) + expect(proposalDataAfter.rateToken).to.be.equal(serviceData.token) expect(proposalDataAfter.rateAmount.toString()).to.be.equal('15') expect(proposalDataAfter.dataUri).to.be.equal(cid2) expect(proposalDataAfter.platformId).to.be.equal(alicePlatformId) @@ -1068,7 +1108,7 @@ describe('TalentLayer protocol global testing', function () { const signature = await getSignatureForProposal(platformOneOwner, carolTlId, 4, cid2) const tx = talentLayerService .connect(carol) - .createProposalWithReferrer( + .createProposal( carolTlId, 4, 15, @@ -1097,7 +1137,7 @@ describe('TalentLayer protocol global testing', function () { const signature = await getSignatureForProposal(platformOneOwner, carolTlId, 6, cid2) const tx = await talentLayerService .connect(carol) - .createProposalWithReferrer( + .createProposal( carolTlId, 6, 2000000, @@ -1120,7 +1160,7 @@ describe('TalentLayer protocol global testing', function () { // Proposal data check after the proposal // @dev: rateToken field not used any more - expect(proposalDataAfter.rateToken).to.be.equal(ethers.constants.AddressZero) + expect(proposalDataAfter.rateToken).to.be.equal(serviceData.token) expect(proposalDataAfter.rateAmount.toString()).to.be.equal('2000000') expect(proposalDataAfter.dataUri).to.be.equal(cid2) expect(proposalDataAfter.platformId).to.be.equal(alicePlatformId) @@ -1155,7 +1195,7 @@ describe('TalentLayer protocol global testing', function () { const signature = await getSignatureForProposal(platformOneOwner, carolTlId, 7, cid2) const tx = await talentLayerService .connect(carol) - .createProposalWithReferrer( + .createProposal( carolTlId, 7, 2000000, @@ -1178,7 +1218,7 @@ describe('TalentLayer protocol global testing', function () { // Proposal data check after the proposal // @dev: rateToken field not used any more - expect(proposalDataAfter.rateToken).to.be.equal(ethers.constants.AddressZero) + expect(proposalDataAfter.rateToken).to.be.equal(serviceData.token) expect(proposalDataAfter.rateAmount.toString()).to.be.equal('2000000') expect(proposalDataAfter.dataUri).to.be.equal(cid2) expect(proposalDataAfter.platformId).to.be.equal(alicePlatformId) @@ -1208,9 +1248,19 @@ describe('TalentLayer protocol global testing', function () { const signature = await getSignatureForProposal(platformOneOwner, bobTlId, 1, cid2) const tx = talentLayerService .connect(bob) - .createProposal(bobTlId, 1, 15, alicePlatformId, cid2, proposalExpirationDate, signature, { - value: alicePlatformProposalPostingFee, - }) + .createProposal( + bobTlId, + 1, + 15, + alicePlatformId, + cid2, + proposalExpirationDate, + signature, + 0, + { + value: alicePlatformProposalPostingFee, + }, + ) await expect(tx).to.be.revertedWith('proposal already exist') }) @@ -1225,7 +1275,7 @@ describe('TalentLayer protocol global testing', function () { const signature = await getSignatureForProposal(platformOneOwner, eveTid.toNumber(), 1, cid2) await talentLayerService .connect(eve) - .createProposal(eveTid, 1, 15, alicePlatformId, cid2, expiredProposalDate, signature, { + .createProposal(eveTid, 1, 15, alicePlatformId, cid2, expiredProposalDate, signature, 0, { value: alicePlatformProposalPostingFee, }) }) @@ -1244,9 +1294,19 @@ describe('TalentLayer protocol global testing', function () { const signature = await getSignatureForProposal(bob, carolTlId, 1, cid2) await talentLayerService .connect(carol) - .createProposal(carolTlId, 1, 16, bobPlatformId, cid2, proposalExpirationDate, signature, { - value: bobPlatformProposalPostingFee, - }) + .createProposal( + carolTlId, + 1, + 16, + bobPlatformId, + cid2, + proposalExpirationDate, + signature, + 0, + { + value: bobPlatformProposalPostingFee, + }, + ) await talentLayerService.services(1) // get proposal info const carolTid = await talentLayerID.ids(carol.address) @@ -1257,6 +1317,8 @@ describe('TalentLayer protocol global testing', function () { const proposalDataBefore = await talentLayerService.getProposal(1, bobTlId) expect(proposalDataBefore.rateAmount.toString()).to.be.equal('15') + const serviceData = await talentLayerService.services(1) + const tx = await talentLayerService .connect(bob) .updateProposal(bobTlId, 1, 18, cid, proposalExpirationDate, aliceTlId) @@ -1268,7 +1330,7 @@ describe('TalentLayer protocol global testing', function () { expect(proposalDataAfter.rateAmount.toString()).to.be.equal('18') expect(proposalDataAfter.expirationDate).to.be.equal(proposalExpirationDate) // @dev: This field is deprecated and should always be zero address - expect(proposalDataAfter.rateToken.toString()).to.be.equal(ethers.constants.AddressZero) + expect(proposalDataAfter.rateToken.toString()).to.be.equal(serviceData.token) expect(proposalDataAfter.dataUri).to.be.equal(cid) expect(proposalDataAfter.referrerId).to.be.equal(aliceTlId) }) @@ -1342,6 +1404,7 @@ describe('TalentLayer protocol global testing', function () { cid, proposalExpirationDate, signature, + 0, { value: bobPlatformProposalPostingFee }, ) }) @@ -1363,6 +1426,7 @@ describe('TalentLayer protocol global testing', function () { cid, proposalExpirationDate, signature, + 0, { value: bobPlatformProposalPostingFee }, ) }) @@ -1380,6 +1444,7 @@ describe('TalentLayer protocol global testing', function () { cid, proposalExpirationDate, signature2, + 0, ) await expect(tx).to.revertedWith('Service not exist') }) @@ -1484,6 +1549,7 @@ describe('TalentLayer protocol global testing', function () { cid2, proposalExpirationDate, signature, + 0, { value: alicePlatformProposalPostingFee, }, @@ -1811,6 +1877,7 @@ describe('TalentLayer protocol global testing', function () { cid, proposalExpirationDate, signature2, + 0, { value: alicePlatformProposalPostingFee, }, @@ -1980,6 +2047,7 @@ describe('TalentLayer protocol global testing', function () { cid, proposalExpirationDate, signature, + 0, { value: bobPlatformProposalPostingFee }, ) }) @@ -2000,6 +2068,7 @@ describe('TalentLayer protocol global testing', function () { cid, proposalExpirationDate, signature, + 0, { value: bobPlatformProposalPostingFee }, ) }) diff --git a/test/batch/pausableEscrow.ts b/test/batch/pausableEscrow.ts index 3b3da14c..47269ebc 100644 --- a/test/batch/pausableEscrow.ts +++ b/test/batch/pausableEscrow.ts @@ -84,6 +84,7 @@ async function deployAndSetup(): Promise< cid, proposalExpirationDate, signature2, + 0, ) return [talentLayerEscrow, talentLayerService, talentLayerPlatformID, talentLayerReview] diff --git a/test/batch/platformVerification.ts b/test/batch/platformVerification.ts index 57bc6072..4aba075a 100644 --- a/test/batch/platformVerification.ts +++ b/test/batch/platformVerification.ts @@ -188,6 +188,7 @@ describe('Platform verification', function () { cid, proposalExpirationDate, signature, + 0, ) await expect(tx).to.not.reverted @@ -231,6 +232,7 @@ describe('Platform verification', function () { cid, proposalExpirationDate, signature, + 0, ) await expect(tx).to.not.reverted diff --git a/test/batch/serviceCompletion.ts b/test/batch/serviceCompletion.ts index c5b79788..acfe091a 100644 --- a/test/batch/serviceCompletion.ts +++ b/test/batch/serviceCompletion.ts @@ -143,6 +143,7 @@ describe('Completion of service', function () { cid, proposalExpirationDate, signatureProposal, + 0, ) // Validate the proposal by locking the funds in the escrow diff --git a/test/batch/transferProfileIds.ts b/test/batch/transferProfileIds.ts index cc03e3f3..2986c559 100644 --- a/test/batch/transferProfileIds.ts +++ b/test/batch/transferProfileIds.ts @@ -131,6 +131,7 @@ describe('Transfer of TalentLayer IDs', function () { cid, proposalExpirationDate, signature, + 0, ) expect(await talentLayerID.hasActivity(carolTlId)).to.be.true From d499ac572ed81e45712b3271ce3bfa9e50f63a60 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 14 Jun 2023 19:52:11 +0200 Subject: [PATCH 58/99] Removed comment Signed-off-by: Quentin D.C --- test/batch/fullWorkflow.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index 1b16dcc3..1d72ade7 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -1329,7 +1329,6 @@ describe('TalentLayer protocol global testing', function () { .withArgs(1, bobTlId, cid, 18, proposalExpirationDate) expect(proposalDataAfter.rateAmount.toString()).to.be.equal('18') expect(proposalDataAfter.expirationDate).to.be.equal(proposalExpirationDate) - // @dev: This field is deprecated and should always be zero address expect(proposalDataAfter.rateToken.toString()).to.be.equal(serviceData.token) expect(proposalDataAfter.dataUri).to.be.equal(cid) expect(proposalDataAfter.referrerId).to.be.equal(aliceTlId) From 04ad7a5b933c323d52797019a35c0d28c8b41c55 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 14 Jun 2023 21:18:22 +0200 Subject: [PATCH 59/99] Renamed variables, removed "rate" Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 6 +- contracts/TalentLayerService.sol | 66 +++++++------------- contracts/interfaces/ITalentLayerService.sol | 28 ++------- 3 files changed, 31 insertions(+), 69 deletions(-) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index ce710542..29c8d633 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -489,7 +489,7 @@ contract TalentLayerEscrow is } uint256 transactionAmount = _calculateTotalWithFees( - proposal.rateAmount, + proposal.amount, originServiceCreationPlatform.originServiceFeeRate, originProposalCreationPlatform.originValidatedProposalFeeRate, service.referralAmount @@ -518,8 +518,8 @@ contract TalentLayerEscrow is sender: sender, receiver: receiver, token: service.token, - totalAmount: proposal.rateAmount, - amount: proposal.rateAmount, + totalAmount: proposal.amount, + amount: proposal.amount, releasedAmount: 0, serviceId: _serviceId, proposalId: _proposalId, diff --git a/contracts/TalentLayerService.sol b/contracts/TalentLayerService.sol index 76bbc925..a377a84e 100644 --- a/contracts/TalentLayerService.sol +++ b/contracts/TalentLayerService.sol @@ -64,8 +64,8 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @notice Proposal information struct * @param status the current status of a service * @param ownerId the talentLayerId of the seller - * @param DEPRECATED - rateToken the token choose for the payment - * @param rateAmount the amount of token chosen + * @param token the token choose for the payment + * @param amount the amount of token chosen * @param dataUri token Id to IPFS URI mapping * @param expirationDate the timeout for the proposal * @param referrerId the id of the referrer (Zero if no referrer) @@ -73,8 +73,8 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU struct Proposal { ProposalStatus status; uint256 ownerId; - address rateToken; - uint256 rateAmount; + address token; + uint256 amount; uint256 platformId; string dataUri; uint256 expirationDate; @@ -138,7 +138,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param ownerId The talentLayerId of the seller who made the proposal * @param dataUri token Id to IPFS URI mapping * @param status proposal status - * @param rateAmount the amount of token chosen + * @param amount the amount of token chosen * @param platformId the platform ID on which the proposal was created * @param expirationDate the timeout for the proposal * @param referrerId the id of the referrer (Zero if no referrer) @@ -148,7 +148,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU uint256 ownerId, string dataUri, ProposalStatus status, - uint256 rateAmount, + uint256 amount, uint256 platformId, uint256 expirationDate, uint256 referrerId @@ -159,33 +159,15 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param serviceId The service id * @param ownerId The talentLayerId of the seller who made the proposal * @param dataUri token Id to IPFS URI mapping - * @param rateToken the token choose for the payment - * @param rateAmount the amount of token chosen - * @param expirationDate the timeout for the proposal - */ - event ProposalUpdated( - uint256 serviceId, - uint256 ownerId, - string dataUri, - address rateToken, - uint256 rateAmount, - uint256 expirationDate - ); - - /** - * @notice Emitted after an existing proposal has been updated - * @param serviceId The service id - * @param ownerId The talentLayerId of the seller who made the proposal - * @param dataUri token Id to IPFS URI mapping - * @param rateAmount the amount of token chosen + * @param amount the amount of token chosen * @param expirationDate the timeout for the proposal * @param referrerId the id of the referrer (Zero if no referrer) */ - event ProposalUpdatedWithoutToken( + event ProposalUpdated( uint256 serviceId, uint256 ownerId, string dataUri, - uint256 rateAmount, + uint256 amount, uint256 expirationDate, uint256 referrerId ); @@ -378,7 +360,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @notice Allows an seller to propose his service for a service * @param _profileId The TalentLayer ID of the user owner of the proposal * @param _serviceId The service linked to the new proposal - * @param _rateAmount the amount of token chosen + * @param _amount the amount of token chosen * @param _dataUri token Id to IPFS URI mapping * @param _platformId platform ID from where the proposal is created * @param _expirationDate the time before the proposal is automatically validated @@ -388,7 +370,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU function createProposal( uint256 _profileId, uint256 _serviceId, - uint256 _rateAmount, + uint256 _amount, uint256 _platformId, string calldata _dataUri, uint256 _expirationDate, @@ -396,13 +378,13 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU uint256 _referrerId ) public payable onlyOwnerOrDelegate(_profileId) { Service storage service = services[_serviceId]; - _validateProposal(_profileId, _serviceId, _rateAmount, _platformId, _dataUri, _signature, _referrerId); + _validateProposal(_profileId, _serviceId, _amount, _platformId, _dataUri, _signature, _referrerId); proposals[_serviceId][_profileId] = Proposal({ status: ProposalStatus.Pending, ownerId: _profileId, - rateToken: service.token, - rateAmount: _rateAmount, + token: service.token, + amount: _amount, platformId: _platformId, dataUri: _dataUri, expirationDate: _expirationDate, @@ -419,7 +401,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU _profileId, _dataUri, ProposalStatus.Pending, - _rateAmount, + _amount, _platformId, _expirationDate, _referrerId @@ -430,7 +412,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @notice Allows the owner to update his own proposal for a given service * @param _profileId The TalentLayer ID of the user * @param _serviceId The service linked to the new proposal - * @param _rateAmount the amount of token chosen + * @param _amount the amount of token chosen * @param _dataUri token Id to IPFS URI mapping * @param _expirationDate the time before the proposal is automatically validated * @param _referrerId the id of the referrer (Zero if no referrer) @@ -438,7 +420,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU function updateProposal( uint256 _profileId, uint256 _serviceId, - uint256 _rateAmount, + uint256 _amount, string calldata _dataUri, uint256 _expirationDate, uint256 _referrerId @@ -449,18 +431,18 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU require(proposal.ownerId == _profileId, "Not the owner"); require(bytes(_dataUri).length == 46, "Invalid cid"); require(proposal.status != ProposalStatus.Validated, "Already validated"); - require(_rateAmount >= allowedTokenList[service.token].minimumTransactionAmount, "Amount too low"); + require(_amount >= allowedTokenList[service.token].minimumTransactionAmount, "Amount too low"); if (_referrerId != 0) { tlId.isValid(_referrerId); } - proposal.rateAmount = _rateAmount; + proposal.amount = _amount; proposal.dataUri = _dataUri; proposal.expirationDate = _expirationDate; proposal.referrerId = _referrerId; - emit ProposalUpdatedWithoutToken(_serviceId, _profileId, _dataUri, _rateAmount, _expirationDate, _referrerId); + emit ProposalUpdated(_serviceId, _profileId, _dataUri, _amount, _expirationDate, _referrerId); } /** @@ -513,7 +495,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU Service storage service = services[_serviceId]; Proposal storage proposal = proposals[_serviceId][service.acceptedProposalId]; - uint256 releasedPercentage = (_releasedAmount * 100) / proposal.rateAmount; + uint256 releasedPercentage = (_releasedAmount * 100) / proposal.amount; if (releasedPercentage >= minCompletionPercentage) { service.status = Status.Finished; } else { @@ -630,7 +612,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @notice Validate a new proposal * @param _profileId The TalentLayer ID of the user * @param _serviceId The service linked to the new proposal - * @param _rateAmount the amount of token chosen + * @param _amount the amount of token chosen * @param _platformId platform ID on which the Proposal was created * @param _dataUri token Id to IPFS URI mapping * @param _signature platform signature to allow the operation @@ -638,7 +620,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU function _validateProposal( uint256 _profileId, uint256 _serviceId, - uint256 _rateAmount, + uint256 _amount, uint256 _platformId, string calldata _dataUri, bytes calldata _signature, @@ -648,7 +630,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU require(msg.value == proposalPostingFee, "Non-matching funds"); Service storage service = services[_serviceId]; - require(_rateAmount >= allowedTokenList[service.token].minimumTransactionAmount, "Amount too low"); + require(_amount >= allowedTokenList[service.token].minimumTransactionAmount, "Amount too low"); require(service.status == Status.Opened, "Service not opened"); require(service.ownerId != 0, "Service not exist"); require(proposals[_serviceId][_profileId].ownerId != _profileId, "proposal already exist"); diff --git a/contracts/interfaces/ITalentLayerService.sol b/contracts/interfaces/ITalentLayerService.sol index 77faf8de..97e3e25d 100644 --- a/contracts/interfaces/ITalentLayerService.sol +++ b/contracts/interfaces/ITalentLayerService.sol @@ -33,8 +33,8 @@ interface ITalentLayerService { struct Proposal { ProposalStatus status; uint256 ownerId; - address rateToken; - uint256 rateAmount; + address token; + uint256 amount; uint256 platformId; string dataUri; uint256 expirationDate; @@ -51,15 +51,6 @@ interface ITalentLayerService { ) external view returns (Service memory, Proposal memory); function createService( - Status _status, - uint256 _tokenId, - uint256 _platformId, - uint256 _ownerId, - string calldata _dataUri, - address _token - ) external returns (uint256); - - function createServiceWithReferral( uint256 _profileId, uint256 _platformId, string calldata _dataUri, @@ -71,17 +62,7 @@ interface ITalentLayerService { function createProposal( uint256 _profileId, uint256 _serviceId, - uint256 _rateAmount, - uint256 _platformId, - string calldata _dataUri, - uint256 _expirationDate, - bytes calldata _signature - ) external; - - function createProposalWithReferrer( - uint256 _profileId, - uint256 _serviceId, - uint256 _rateAmount, + uint256 _amount, uint256 _platformId, string calldata _dataUri, uint256 _expirationDate, @@ -94,7 +75,7 @@ interface ITalentLayerService { function updateProposal( uint256 _profileId, uint256 _serviceId, - uint256 _rateAmount, + uint256 _amount, string calldata _dataUri, uint256 _expirationDate, uint256 _referrerId @@ -106,7 +87,6 @@ interface ITalentLayerService { uint256 _profileId, uint256 _serviceId, uint256 _referralAmount, - address _token, string calldata _dataUri ) external; } From 0f95e33ce67e1465828350c87a36fcf3b665aae2 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 14 Jun 2023 21:18:49 +0200 Subject: [PATCH 60/99] Updated tests Signed-off-by: Quentin D.C --- test/batch/disputeResolution.ts | 2 +- test/batch/fullWorkflow.ts | 44 ++++++++++++++++----------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/test/batch/disputeResolution.ts b/test/batch/disputeResolution.ts index 640183c2..4695224b 100644 --- a/test/batch/disputeResolution.ts +++ b/test/batch/disputeResolution.ts @@ -160,7 +160,7 @@ async function createTransaction( // we need to retreive the Bob proposal dataUri const proposal = await talentLayerService.proposals(serviceId, bobTlId) - const value = proposal.rateToken === ethAddress ? totalTransactionAmount : 0 + const value = proposal.token === ethAddress ? totalTransactionAmount : 0 let tx: ContractTransaction tokenAddress === ethAddress diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index 1d72ade7..26e4db6a 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -59,7 +59,7 @@ describe('TalentLayer protocol global testing', function () { networkConfig: NetworkConfig, chainId: number - const nonListedRateToken = '0x6b175474e89094c44da98b954eedeac495271d0f' + const nonListedtoken = '0x6b175474e89094c44da98b954eedeac495271d0f' const referralAmount = 20000 before(async function () { @@ -779,7 +779,7 @@ describe('TalentLayer protocol global testing', function () { const signature = await getSignatureForService(platformOneOwner, aliceTlId, 0, cid) const tx = talentLayerService .connect(alice) - .createService(aliceTlId, alicePlatformId, cid, signature, nonListedRateToken, 0, { + .createService(aliceTlId, alicePlatformId, cid, signature, nonListedtoken, 0, { value: alicePlatformServicePostingFee, }) @@ -1086,9 +1086,9 @@ describe('TalentLayer protocol global testing', function () { expect(serviceData.ownerId).to.be.equal(aliceTlId) // Proposal data check after the proposal - // @dev: rateToken field not used any more - expect(proposalDataAfter.rateToken).to.be.equal(serviceData.token) - expect(proposalDataAfter.rateAmount.toString()).to.be.equal('15') + // @dev: token field not used any more + expect(proposalDataAfter.token).to.be.equal(serviceData.token) + expect(proposalDataAfter.amount.toString()).to.be.equal('15') expect(proposalDataAfter.dataUri).to.be.equal(cid2) expect(proposalDataAfter.platformId).to.be.equal(alicePlatformId) expect(proposalDataAfter.expirationDate).to.be.equal(proposalExpirationDate) @@ -1159,9 +1159,9 @@ describe('TalentLayer protocol global testing', function () { expect(serviceData.ownerId).to.be.equal(aliceTlId) // Proposal data check after the proposal - // @dev: rateToken field not used any more - expect(proposalDataAfter.rateToken).to.be.equal(serviceData.token) - expect(proposalDataAfter.rateAmount.toString()).to.be.equal('2000000') + // @dev: token field not used any more + expect(proposalDataAfter.token).to.be.equal(serviceData.token) + expect(proposalDataAfter.amount.toString()).to.be.equal('2000000') expect(proposalDataAfter.dataUri).to.be.equal(cid2) expect(proposalDataAfter.platformId).to.be.equal(alicePlatformId) expect(proposalDataAfter.expirationDate).to.be.equal(proposalExpirationDate) @@ -1217,9 +1217,9 @@ describe('TalentLayer protocol global testing', function () { expect(serviceData.ownerId).to.be.equal(aliceTlId) // Proposal data check after the proposal - // @dev: rateToken field not used any more - expect(proposalDataAfter.rateToken).to.be.equal(serviceData.token) - expect(proposalDataAfter.rateAmount.toString()).to.be.equal('2000000') + // @dev: token field not used any more + expect(proposalDataAfter.token).to.be.equal(serviceData.token) + expect(proposalDataAfter.amount.toString()).to.be.equal('2000000') expect(proposalDataAfter.dataUri).to.be.equal(cid2) expect(proposalDataAfter.platformId).to.be.equal(alicePlatformId) expect(proposalDataAfter.expirationDate).to.be.equal(proposalExpirationDate) @@ -1315,7 +1315,7 @@ describe('TalentLayer protocol global testing', function () { it('Bob can update his first proposal ', async function () { const proposalDataBefore = await talentLayerService.getProposal(1, bobTlId) - expect(proposalDataBefore.rateAmount.toString()).to.be.equal('15') + expect(proposalDataBefore.amount.toString()).to.be.equal('15') const serviceData = await talentLayerService.services(1) @@ -1327,9 +1327,9 @@ describe('TalentLayer protocol global testing', function () { expect(tx) .to.emit(talentLayerService, 'ProposalUpdatedWithoutToken') .withArgs(1, bobTlId, cid, 18, proposalExpirationDate) - expect(proposalDataAfter.rateAmount.toString()).to.be.equal('18') + expect(proposalDataAfter.amount.toString()).to.be.equal('18') expect(proposalDataAfter.expirationDate).to.be.equal(proposalExpirationDate) - expect(proposalDataAfter.rateToken.toString()).to.be.equal(serviceData.token) + expect(proposalDataAfter.token.toString()).to.be.equal(serviceData.token) expect(proposalDataAfter.dataUri).to.be.equal(cid) expect(proposalDataAfter.referrerId).to.be.equal(aliceTlId) }) @@ -1607,12 +1607,12 @@ describe('TalentLayer protocol global testing', function () { const originValidatedProposalFeeRate = alicePlatformData.originValidatedProposalFeeRate const referralAmount = service.referralAmount - const totalAmountWithReferral = proposal.rateAmount + const totalAmountWithReferral = proposal.amount .add( - proposal.rateAmount + proposal.amount .mul(protocolEscrowFeeRate) - .add(proposal.rateAmount.mul(originServiceFeeRate)) - .add(proposal.rateAmount.mul(originValidatedProposalFeeRate)) + .add(proposal.amount.mul(originServiceFeeRate)) + .add(proposal.amount.mul(originValidatedProposalFeeRate)) .div(FEE_DIVIDER), ) .add(referralAmount) @@ -2145,12 +2145,12 @@ describe('TalentLayer protocol global testing', function () { const originValidatedProposalFeeRate = alicePlatformData.originValidatedProposalFeeRate const referralAmount = service.referralAmount - const totalAmountWithReferral = proposal.rateAmount + const totalAmountWithReferral = proposal.amount .add( - proposal.rateAmount + proposal.amount .mul(protocolEscrowFeeRate) - .add(proposal.rateAmount.mul(originServiceFeeRate)) - .add(proposal.rateAmount.mul(originValidatedProposalFeeRate)) + .add(proposal.amount.mul(originServiceFeeRate)) + .add(proposal.amount.mul(originValidatedProposalFeeRate)) .div(FEE_DIVIDER), ) .add(referralAmount) From 02de40fef8756bfe3d2feeb6bc09768a240a3ee7 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 14 Jun 2023 21:19:34 +0200 Subject: [PATCH 61/99] Created archive interfaces Updates archive escrowV1 contract Signed-off-by: Quentin D.C --- contracts/archive/TalentLayerEscrowV1.sol | 18 ++--- .../interfaces/ITalentLayerEscrowV1.sol | 73 +++++++++++++++++ .../interfaces/ITalentLayerServiceV1.sol | 78 +++++++++++++++++++ 3 files changed, 160 insertions(+), 9 deletions(-) create mode 100644 contracts/archive/interfaces/ITalentLayerEscrowV1.sol create mode 100644 contracts/archive/interfaces/ITalentLayerServiceV1.sol diff --git a/contracts/archive/TalentLayerEscrowV1.sol b/contracts/archive/TalentLayerEscrowV1.sol index fdf3faf4..f6d31699 100644 --- a/contracts/archive/TalentLayerEscrowV1.sol +++ b/contracts/archive/TalentLayerEscrowV1.sol @@ -7,7 +7,7 @@ import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; -import {ITalentLayerService} from "../interfaces/ITalentLayerService.sol"; +import {ITalentLayerServiceV1} from "./interfaces/ITalentLayerServiceV1.sol"; import {ITalentLayerID} from "../interfaces/ITalentLayerID.sol"; import {ITalentLayerPlatformID} from "../interfaces/ITalentLayerPlatformID.sol"; import "../libs/ERC2771RecipientUpgradeable.sol"; @@ -263,7 +263,7 @@ contract TalentLayerEscrowV1 is /** * @notice Instance of TalentLayerService.sol */ - ITalentLayerService private talentLayerServiceContract; + ITalentLayerServiceV1 private talentLayerServiceContract; /** * @notice Instance of TalentLayerID.sol @@ -354,7 +354,7 @@ contract TalentLayerEscrowV1 is __Ownable_init(); __UUPSUpgradeable_init(); - talentLayerServiceContract = ITalentLayerService(_talentLayerServiceAddress); + talentLayerServiceContract = ITalentLayerServiceV1(_talentLayerServiceAddress); talentLayerIdContract = ITalentLayerID(_talentLayerIDAddress); talentLayerPlatformIdContract = ITalentLayerPlatformID(_talentLayerPlatformIDAddress); protocolWallet = payable(_protocolWallet); @@ -451,8 +451,8 @@ contract TalentLayerEscrowV1 is string memory _originDataUri ) external payable whenNotPaused returns (uint256) { ( - ITalentLayerService.Service memory service, - ITalentLayerService.Proposal memory proposal + ITalentLayerServiceV1.Service memory service, + ITalentLayerServiceV1.Proposal memory proposal ) = talentLayerServiceContract.getServiceAndProposal(_serviceId, _proposalId); (address sender, address receiver) = talentLayerIdContract.ownersOf(service.ownerId, proposal.ownerId); @@ -478,8 +478,8 @@ contract TalentLayerEscrowV1 is require(_msgSender() == sender, "Access denied"); require(proposal.ownerId == _proposalId, "Incorrect proposal ID"); require(proposal.expirationDate >= block.timestamp, "Proposal expired"); - require(service.status == ITalentLayerService.Status.Opened, "Service status not open"); - require(proposal.status == ITalentLayerService.ProposalStatus.Pending, "Proposal status not pending"); + require(service.status == ITalentLayerServiceV1.Status.Opened, "Service status not open"); + require(proposal.status == ITalentLayerServiceV1.ProposalStatus.Pending, "Proposal status not pending"); require(bytes(_metaEvidence).length == 46, "Invalid cid"); require( keccak256(abi.encodePacked(proposal.dataUri)) == keccak256(abi.encodePacked(_originDataUri)), @@ -914,8 +914,8 @@ contract TalentLayerEscrowV1 is function _distributeFees(uint256 _transactionId, uint256 _releaseAmount) private { Transaction storage transaction = transactions[_transactionId]; ( - ITalentLayerService.Service memory service, - ITalentLayerService.Proposal memory proposal + ITalentLayerServiceV1.Service memory service, + ITalentLayerServiceV1.Proposal memory proposal ) = talentLayerServiceContract.getServiceAndProposal(transaction.serviceId, transaction.proposalId); uint256 originServiceCreationPlatformId = service.platformId; diff --git a/contracts/archive/interfaces/ITalentLayerEscrowV1.sol b/contracts/archive/interfaces/ITalentLayerEscrowV1.sol new file mode 100644 index 00000000..d289022f --- /dev/null +++ b/contracts/archive/interfaces/ITalentLayerEscrowV1.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +/** + * @title Platform ID Interface + * @author TalentLayer Team | Website: https://talentlayer.org | Twitter: @talentlayer + */ +interface ITalentLayerEscrowV1 { + struct Transaction { + uint256 id; + address sender; + address receiver; + address token; + uint256 amount; + uint256 serviceId; + uint16 protocolEscrowFeeRate; + uint16 originServiceFeeRate; + uint16 originValidatedProposalFeeRate; + uint256 disputeId; + uint256 senderFee; + uint256 receiverFee; + uint256 lastInteraction; + Status status; + // Arbitrator arbitrator; + bytes arbitratorExtraData; + uint256 arbitrationFeeTimeout; + } + + enum Status { + NoDispute, // no dispute has arisen about the transaction + WaitingSender, // receiver has paid arbitration fee, while sender still has to do it + WaitingReceiver, // sender has paid arbitration fee, while receiver still has to do it + DisputeCreated, // both parties have paid the arbitration fee and a dispute has been created + Resolved // the transaction is solved (either no dispute has ever arisen or the dispute has been resolved) + } + + function getClaimableFeeBalance(address _token) external view returns (uint256 balance); + + function getTransactionDetails(uint256 _transactionId) external view returns (Transaction memory); + + function updateProtocolEscrowFeeRate(uint16 _protocolEscrowFeeRate) external; + + function updateProtocolWallet(address payable _protocolWallet) external; + + function createTransaction( + uint256 _serviceId, + uint256 _proposalId, + string memory _metaEvidence, + string memory originDataUri + ) external payable returns (uint256); + + function release(uint256 _transactionId, uint256 _amount) external; + + function reimburse(uint256 _transactionId, uint256 _amount) external; + + function claim(uint256 _platformId, address _tokenAddress) external; + + function claimAll(uint256 _platformId) external; + + function payArbitrationFeeBySender(uint256 _transactionId) external payable; + + function payArbitrationFeeByReceiver(uint256 _transactionId) external payable; + + function timeOutBySender(uint256 _transactionId) external; + + function timeOutByReceiver(uint256 _transactionId) external; + + function submitEvidence(uint256 _transactionId, string memory _evidence) external; + + function appeal(uint256 _transactionId) external payable; + + function rule(uint256 _disputeID, uint256 _ruling) external; +} diff --git a/contracts/archive/interfaces/ITalentLayerServiceV1.sol b/contracts/archive/interfaces/ITalentLayerServiceV1.sol new file mode 100644 index 00000000..41876fa5 --- /dev/null +++ b/contracts/archive/interfaces/ITalentLayerServiceV1.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +/** + * @title Platform ID Interface + * @author TalentLayer Team | Website: https://talentlayer.org | Twitter: @talentlayer + */ +interface ITalentLayerServiceV1 { + enum Status { + Opened, + Confirmed, + Finished, + Cancelled, + Uncompleted + } + + enum ProposalStatus { + Pending, + Validated + } + + struct Service { + Status status; + uint256 ownerId; + uint256 acceptedProposalId; + string dataUri; + uint256 transactionId; + uint256 platformId; + } + + struct Proposal { + ProposalStatus status; + uint256 ownerId; + address rateToken; + uint256 rateAmount; + uint256 platformId; + string dataUri; + uint256 expirationDate; + } + + function getService(uint256 _serviceId) external view returns (Service memory); + + function getProposal(uint256 _serviceId, uint256 _proposal) external view returns (Proposal memory); + + function getServiceAndProposal( + uint256 _serviceId, + uint256 _proposal + ) external view returns (Service memory, Proposal memory); + + function createService( + Status _status, + uint256 _tokenId, + uint256 _platformId, + uint256 _ownerId, + string calldata _dataUri + ) external returns (uint256); + + function createProposal( + uint256 _serviceId, + address _rateToken, + uint256 _rateAmount, + uint256 _platformId, + string calldata _dataUri + ) external; + + function afterDeposit(uint256 _serviceId, uint256 _proposalId, uint256 _transactionId) external; + + function updateProposal( + uint256 _serviceId, + address _rateToken, + uint256 _rateAmount, + string calldata _dataUri + ) external; + + function afterFullPayment(uint256 _serviceId, uint256 _releasedAmount) external; + + function updateServiceData(uint256 _serviceId, string calldata _dataUri) external; +} From 5c1d36cb3d73312602594ab6f29add8992812aa8 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 14 Jun 2023 21:30:45 +0200 Subject: [PATCH 62/99] Refactored into ternary Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index 29c8d633..b00c1d09 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -483,10 +483,7 @@ contract TalentLayerEscrow is ? talentLayerPlatformIdContract.getPlatform(proposal.platformId) : originServiceCreationPlatform; - uint256 referralAmount = service.referralAmount; - if (proposal.referrerId == 0) { - referralAmount = 0; - } + uint256 referralAmount = proposal.referrerId == 0 ? 0 : service.referralAmount; uint256 transactionAmount = _calculateTotalWithFees( proposal.amount, From de4a60dcfe7269f04bfe2e2d4fa779471e257295 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 14 Jun 2023 21:43:28 +0200 Subject: [PATCH 63/99] Quick refacto Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index b00c1d09..cd5d31e1 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -922,11 +922,10 @@ contract TalentLayerEscrow is */ function _reimburse(uint256 _transactionId, uint256 _amount) private { Transaction storage transaction = transactions[_transactionId]; - uint256 reimbursedReferralAmount; - if (transaction.referrerId != 0) { - reimbursedReferralAmount = (_amount * transaction.referralAmount) / (transaction.totalAmount); - } + //If no referrerId (=0), the referralAmount will always be 0 + uint256 reimbursedReferralAmount = (_amount * transaction.referralAmount) / (transaction.totalAmount); + uint256 totalReimburseAmount = _calculateTotalWithFees( _amount, transaction.originServiceFeeRate, From 6a68d11f2dd7a5c28e3f2b4f9757b545dc872a4f Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 14 Jun 2023 23:21:39 +0200 Subject: [PATCH 64/99] Added referrerBalance mapping instead of transferring balance directly to referrer Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 55 ++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index cd5d31e1..9a9fff2c 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -155,6 +155,14 @@ contract TalentLayerEscrow is */ event FeesClaimed(uint256 _platformId, address indexed _token, uint256 _amount); + /** + * @notice Emitted after a referrer withdraws its balance + * @param _referrerId The Platform ID to which the balance is transferred. + * @param _token The address of the token used for the payment. + * @param _amount The amount transferred. + */ + event ReferralAmountClaimed(uint256 _referrerId, address indexed _token, uint256 _amount); + /** * @notice Emitted after an origin service fee is released to a platform's balance * @param _platformId The platform ID. @@ -280,6 +288,14 @@ contract TalentLayerEscrow is */ mapping(uint256 => mapping(address => uint256)) private platformIdToTokenToBalance; + /** + * @notice Mapping from referrerId to Token address to Token Balance + * Represents the amount of ETH or token present on this contract which + * belongs to a referrer and can be withdrawn. + * @dev address(0) is reserved to ETH balance + */ + mapping(uint256 => mapping(address => uint256)) private referrerIdToTokenToBalance; + /** * @notice Instance of TalentLayerService.sol */ @@ -402,6 +418,17 @@ contract TalentLayerEscrow is return platformIdToTokenToBalance[platformId][_token]; } + /** + * @dev Only the owner of the referrer ID can execute this function + * @param _token Token address ("0" for ETH) + * @return balance The balance of the referrer + */ + function getClaimableReferralBalance(address _token) external view returns (uint256 balance) { + uint256 referrerId = talentLayerIdContract.ids(_msgSender()); + talentLayerIdContract.isValid(referrerId); + return referrerIdToTokenToBalance[referrerId][_token]; + } + /** * @notice Called to get the details of a transaction * @dev Only the transaction sender or receiver can call this function @@ -755,6 +782,28 @@ contract TalentLayerEscrow is emit FeesClaimed(_platformId, _tokenAddress, amount); } + // =========================== Referrer functions ============================== + + /** + * @notice Allows a referrer to claim its tokens & / or ETH balance. + * @param _referrerId The ID of the referrer claiming the balance. + * @param _tokenAddress The address of the Token contract (address(0) if balance in ETH). + * Emits a BalanceTransferred & a ReferralAmountClaimed events + */ + function claimReferralBalance(uint256 _referrerId, address _tokenAddress) external whenNotPaused { + address payable recipient; + + talentLayerIdContract.isValid(_referrerId); + recipient = payable(talentLayerIdContract.ownerOf(_referrerId)); + + uint256 amount = referrerIdToTokenToBalance[_referrerId][_tokenAddress]; + require(amount > 0, "nothing to claim"); + referrerIdToTokenToBalance[_referrerId][_tokenAddress] = 0; + _safeTransferBalance(recipient, _tokenAddress, amount); + + emit ReferralAmountClaimed(_referrerId, _tokenAddress, amount); + } + // =========================== Arbitrator functions ============================== /** @@ -965,11 +1014,7 @@ contract TalentLayerEscrow is if (transaction.referrerId != 0 && transaction.referralAmount != 0) { uint256 releasedReferralAmount = (_releaseAmount * transaction.referralAmount) / (transaction.totalAmount); - _safeTransferBalance( - payable(talentLayerIdContract.ownerOf(transaction.referrerId)), - transaction.token, - releasedReferralAmount - ); + referrerIdToTokenToBalance[transaction.referrerId][transaction.token] = releasedReferralAmount; emit ReferralAmountReleased( transaction.referrerId, From 064ff851b3a32b956c31f5f242feb59deb262297 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 14 Jun 2023 23:22:02 +0200 Subject: [PATCH 65/99] Updated tests Signed-off-by: Quentin D.C --- test/batch/fullWorkflow.ts | 105 +++++++++++++++++++++++++++---------- 1 file changed, 78 insertions(+), 27 deletions(-) diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index 26e4db6a..5cd48ef3 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -1651,8 +1651,8 @@ describe('TalentLayer protocol global testing', function () { // Bob gets half of the referral amount await expect(tx).to.changeTokenBalances( token, - [talentLayerEscrow.address, alice, carol, bob], - [-releaseAmount.add(releasedReferrerAmount), 0, releaseAmount, releasedReferrerAmount], + [talentLayerEscrow.address, alice, carol], + [-releaseAmount, 0, releaseAmount], ) const alicePlatformBalance = await talentLayerEscrow @@ -1661,15 +1661,29 @@ describe('TalentLayer protocol global testing', function () { const deployerBalance = await talentLayerEscrow .connect(deployer) .getClaimableFeeBalance(token.address) + const referrerBalance = await talentLayerEscrow + .connect(bob) + .getClaimableReferralBalance(token.address) + // Alice gets half of both the originServiceFeeRate and the originValidatedProposalFeeRate expect(alicePlatformBalance).to.be.equal( releaseAmount.mul(originServiceFeeRate + originValidatedProposalFeeRate).div(FEE_DIVIDER), ) - expect(deployerBalance.toString()).to.be.equal( + expect(deployerBalance).to.be.equal( releaseAmount.mul(protocolEscrowFeeRate).div(FEE_DIVIDER), ) - await talentLayerEscrow.connect(alice).claim(alicePlatformId, token.address) - await talentLayerEscrow.connect(deployer).claim(0, token.address) + expect(referrerBalance).to.be.equal(releasedReferrerAmount) + const aliceClaimTx = await talentLayerEscrow + .connect(alice) + .claim(alicePlatformId, token.address) + const deployerClaimTx = await talentLayerEscrow.connect(deployer).claim(0, token.address) + const bobReferrerClaimTx = await talentLayerEscrow + .connect(bob) + .claimReferralBalance(bobTlId, token.address) + + expect(deployerClaimTx).to.changeTokenBalances(token, [alice], [alicePlatformBalance]) + expect(aliceClaimTx).to.changeTokenBalances(token, [deployer], [deployerBalance]) + expect(bobReferrerClaimTx).to.changeTokenBalances(token, [bob], [referrerBalance]) }) it('Alice can reimburse 40% of the escrow to Carol for service 7 which includes a referral amount.', async function () { @@ -1714,11 +1728,11 @@ describe('TalentLayer protocol global testing', function () { .div(transactionDetails.totalAmount) const tx = await talentLayerEscrow.connect(alice).release(aliceTlId, 2, releaseAmount) - // Bob gets half of the referral amount + // Bob gets 10% of the referral amount await expect(tx).to.changeTokenBalances( token, - [talentLayerEscrow.address, alice, carol, bob], - [-releaseAmount.add(releasedReferrerAmount), 0, releaseAmount, releasedReferrerAmount], + [talentLayerEscrow.address, alice, carol], + [-releaseAmount, 0, releaseAmount], ) const alicePlatformBalance = await talentLayerEscrow @@ -1727,15 +1741,29 @@ describe('TalentLayer protocol global testing', function () { const deployerBalance = await talentLayerEscrow .connect(deployer) .getClaimableFeeBalance(token.address) - // Alice gets half of both the originServiceFeeRate and the originValidatedProposalFeeRate + const referrerBalance = await talentLayerEscrow + .connect(bob) + .getClaimableReferralBalance(token.address) + + // Alice gets 10% of both the originServiceFeeRate and the originValidatedProposalFeeRate expect(alicePlatformBalance).to.be.equal( releaseAmount.mul(originServiceFeeRate + originValidatedProposalFeeRate).div(FEE_DIVIDER), ) expect(deployerBalance.toString()).to.be.equal( releaseAmount.mul(protocolEscrowFeeRate).div(FEE_DIVIDER), ) - await talentLayerEscrow.connect(alice).claim(alicePlatformId, token.address) - await talentLayerEscrow.connect(deployer).claim(0, token.address) + expect(referrerBalance.toString()).to.be.equal(releasedReferrerAmount) + const deployerClaimTx = await talentLayerEscrow + .connect(alice) + .claim(alicePlatformId, token.address) + const aliceClaimTx = await talentLayerEscrow.connect(deployer).claim(0, token.address) + const bobReferrerClaimTx = await talentLayerEscrow + .connect(bob) + .claimReferralBalance(bobTlId, token.address) + + expect(deployerClaimTx).to.changeTokenBalances(token, [alice], [alicePlatformBalance]) + expect(aliceClaimTx).to.changeTokenBalances(token, [deployer], [deployerBalance]) + expect(bobReferrerClaimTx).to.changeTokenBalances(token, [bob], [referrerBalance]) // Service status is finished const serviceData = await talentLayerService.services(transactionDetails.serviceId) @@ -2192,13 +2220,11 @@ describe('TalentLayer protocol global testing', function () { .mul(transactionDetails.referralAmount) .div(transactionDetails.amount) - const transaction = await talentLayerEscrow - .connect(alice) - .release(aliceTlId, 4, releaseAmount) + const tx = await talentLayerEscrow.connect(alice).release(aliceTlId, 4, releaseAmount) // Bob gets half of the referral amount - await expect(transaction).to.changeEtherBalances( - [talentLayerEscrow.address, alice, carol, bob], - [-releaseAmount.add(releasedReferrerAmount), 0, releaseAmount, releasedReferrerAmount], + await expect(tx).to.changeEtherBalances( + [talentLayerEscrow.address, alice, carol], + [-releaseAmount, 0, releaseAmount], ) const alicePlatformBalance = await talentLayerEscrow @@ -2207,6 +2233,9 @@ describe('TalentLayer protocol global testing', function () { const deployerBalance = await talentLayerEscrow .connect(deployer) .getClaimableFeeBalance(ethAddress) + const referrerBalance = await talentLayerEscrow + .connect(bob) + .getClaimableReferralBalance(ethAddress) // Alice gets half of both the originServiceFeeRate and the originValidatedProposalFeeRate expect(alicePlatformBalance).to.be.equal( releaseAmount.mul(originServiceFeeRate + originValidatedProposalFeeRate).div(FEE_DIVIDER), @@ -2214,8 +2243,18 @@ describe('TalentLayer protocol global testing', function () { expect(deployerBalance.toString()).to.be.equal( releaseAmount.mul(protocolEscrowFeeRate).div(FEE_DIVIDER), ) - await talentLayerEscrow.connect(alice).claim(alicePlatformId, ethers.constants.AddressZero) - await talentLayerEscrow.connect(deployer).claim(0, ethers.constants.AddressZero) + expect(referrerBalance).to.be.equal(releasedReferrerAmount) + const aliceClaimTx = await talentLayerEscrow + .connect(alice) + .claim(alicePlatformId, ethAddress) + const deployerClaimTx = await talentLayerEscrow.connect(deployer).claim(0, ethAddress) + const bobReferrerClaimTx = await talentLayerEscrow + .connect(bob) + .claimReferralBalance(bobTlId, ethAddress) + + expect(deployerClaimTx).to.changeTokenBalances(token, [alice], [alicePlatformBalance]) + expect(aliceClaimTx).to.changeTokenBalances(token, [deployer], [deployerBalance]) + expect(bobReferrerClaimTx).to.changeTokenBalances(token, [bob], [referrerBalance]) }) it('Alice can reimburse 40% of the escrow to Carol for service 6 which includes a referral amount.', async function () { @@ -2258,13 +2297,11 @@ describe('TalentLayer protocol global testing', function () { .mul(transactionDetails.referralAmount) .div(transactionDetails.totalAmount) - const transaction = await talentLayerEscrow - .connect(alice) - .release(aliceTlId, 4, releaseAmount) + const tx = await talentLayerEscrow.connect(alice).release(aliceTlId, 4, releaseAmount) // Bob gets 10% of the referral amount - await expect(transaction).to.changeEtherBalances( - [talentLayerEscrow.address, alice, carol, bob], - [-releaseAmount.add(releasedReferrerAmount), 0, releaseAmount, releasedReferrerAmount], + await expect(tx).to.changeEtherBalances( + [talentLayerEscrow.address, alice, carol], + [-releaseAmount, 0, releaseAmount], ) const alicePlatformBalance = await talentLayerEscrow @@ -2273,6 +2310,10 @@ describe('TalentLayer protocol global testing', function () { const deployerBalance = await talentLayerEscrow .connect(deployer) .getClaimableFeeBalance(ethAddress) + const referrerBalance = await talentLayerEscrow + .connect(bob) + .getClaimableReferralBalance(ethAddress) + // Alice gets 10% of both the originServiceFeeRate and the originValidatedProposalFeeRate expect(alicePlatformBalance).to.be.equal( releaseAmount.mul(originServiceFeeRate + originValidatedProposalFeeRate).div(FEE_DIVIDER), @@ -2280,8 +2321,18 @@ describe('TalentLayer protocol global testing', function () { expect(deployerBalance.toString()).to.be.equal( releaseAmount.mul(protocolEscrowFeeRate).div(FEE_DIVIDER), ) - await talentLayerEscrow.connect(alice).claim(alicePlatformId, ethers.constants.AddressZero) - await talentLayerEscrow.connect(deployer).claim(0, ethers.constants.AddressZero) + expect(referrerBalance.toString()).to.be.equal(releasedReferrerAmount) + const deployerClaimTx = await talentLayerEscrow + .connect(alice) + .claim(alicePlatformId, ethAddress) + const aliceClaimTx = await talentLayerEscrow.connect(deployer).claim(0, ethAddress) + const bobReferrerClaimTx = await talentLayerEscrow + .connect(bob) + .claimReferralBalance(bobTlId, ethAddress) + + expect(deployerClaimTx).to.changeEtherBalances([alice], [alicePlatformBalance]) + expect(aliceClaimTx).to.changeEtherBalances([deployer], [deployerBalance]) + expect(bobReferrerClaimTx).to.changeEtherBalances([bob], [referrerBalance]) // Service status is finished const serviceData = await talentLayerService.services(transactionDetails.serviceId) From 5cee3cac9deb7dea359458ac201253aea67b5ce8 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 14 Jun 2023 23:22:29 +0200 Subject: [PATCH 66/99] Fixed variable mistake Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index 9a9fff2c..746b164e 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -516,7 +516,7 @@ contract TalentLayerEscrow is proposal.amount, originServiceCreationPlatform.originServiceFeeRate, originProposalCreationPlatform.originValidatedProposalFeeRate, - service.referralAmount + referralAmount ); if (service.token == address(0)) { From d2adcbd1694c7360076ffbf77a47795b3312a3cb Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Thu, 15 Jun 2023 07:41:15 +0200 Subject: [PATCH 67/99] Added 2 require statements Signed-off-by: Quentin D.C --- contracts/TalentLayerService.sol | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/contracts/TalentLayerService.sol b/contracts/TalentLayerService.sol index a377a84e..12f1e0e4 100644 --- a/contracts/TalentLayerService.sol +++ b/contracts/TalentLayerService.sol @@ -630,12 +630,17 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU require(msg.value == proposalPostingFee, "Non-matching funds"); Service storage service = services[_serviceId]; - require(_amount >= allowedTokenList[service.token].minimumTransactionAmount, "Amount too low"); + require( + _amount + service.referralAmount >= allowedTokenList[service.token].minimumTransactionAmount, + "Amount too low" + ); require(service.status == Status.Opened, "Service not opened"); require(service.ownerId != 0, "Service not exist"); require(proposals[_serviceId][_profileId].ownerId != _profileId, "proposal already exist"); - //TODO check to do this ? - // require(service.referralAmount > 0, "Can't refer someone for this service"); + //TODO add test for this ? We keep it or not ? (Good for stats, bad if buyer adds referral amount) + if (_referrerId != 0) { + require(service.referralAmount > 0, "Can't refer someone for this service"); + } require(service.ownerId != _profileId, "can't create for your own service"); require(bytes(_dataUri).length == 46, "Invalid cid"); From 7d6a409d9bafcc585cffb338f3fea140b75be069 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Thu, 15 Jun 2023 07:42:00 +0200 Subject: [PATCH 68/99] Updated tests Signed-off-by: Quentin D.C --- test/batch/fullWorkflow.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index 5cd48ef3..e1fd3670 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -1011,8 +1011,8 @@ describe('TalentLayer protocol global testing', function () { .connect(bob) .createProposal( bobTlId, - 1, - 9, + 3, + 6, alicePlatformId, cid, proposalExpirationDate, @@ -1101,7 +1101,7 @@ describe('TalentLayer protocol global testing', function () { }) it("Carol can't create a proposal with a non existing referrer id", async function () { - // Proposal on the Open service n 4 + // Proposal on the Open service n 1 const platform = await talentLayerPlatformID.getPlatform(alicePlatformId) const alicePlatformProposalPostingFee = platform.servicePostingFee @@ -1110,7 +1110,7 @@ describe('TalentLayer protocol global testing', function () { .connect(carol) .createProposal( carolTlId, - 4, + 1, 15, alicePlatformId, cid2, From b750fbf1e4e145a9cdcfeddd71496f821a255034 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Thu, 15 Jun 2023 10:30:51 +0200 Subject: [PATCH 69/99] Rename variables with "rate" (could not upgrade) Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 14 ++-- contracts/TalentLayerService.sol | 73 +++++++++----------- contracts/interfaces/ITalentLayerService.sol | 12 ++-- 3 files changed, 47 insertions(+), 52 deletions(-) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index 746b164e..827dd3d8 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -513,13 +513,13 @@ contract TalentLayerEscrow is uint256 referralAmount = proposal.referrerId == 0 ? 0 : service.referralAmount; uint256 transactionAmount = _calculateTotalWithFees( - proposal.amount, + proposal.rateAmount, originServiceCreationPlatform.originServiceFeeRate, originProposalCreationPlatform.originValidatedProposalFeeRate, referralAmount ); - if (service.token == address(0)) { + if (service.rateToken == address(0)) { require(msg.value == transactionAmount, "Non-matching funds"); } else { require(msg.value == 0, "Non-matching funds"); @@ -541,9 +541,9 @@ contract TalentLayerEscrow is id: transactionId, sender: sender, receiver: receiver, - token: service.token, - totalAmount: proposal.amount, - amount: proposal.amount, + token: service.rateToken, + totalAmount: proposal.rateAmount, + amount: proposal.rateAmount, releasedAmount: 0, serviceId: _serviceId, proposalId: _proposalId, @@ -566,8 +566,8 @@ contract TalentLayerEscrow is talentLayerServiceContract.afterDeposit(_serviceId, _proposalId, transactionId); - if (service.token != address(0)) { - IERC20Upgradeable(service.token).safeTransferFrom(sender, address(this), transactionAmount); + if (service.rateToken != address(0)) { + IERC20Upgradeable(service.rateToken).safeTransferFrom(sender, address(this), transactionAmount); } _afterCreateTransaction(service.ownerId, proposal.ownerId, transactionId, _metaEvidence); diff --git a/contracts/TalentLayerService.sol b/contracts/TalentLayerService.sol index 12f1e0e4..cbed450b 100644 --- a/contracts/TalentLayerService.sol +++ b/contracts/TalentLayerService.sol @@ -46,7 +46,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param dataUri token Id to IPFS URI mapping * @param transactionId the escrow transaction ID linked to the service * @param platformId the platform ID on which the service was created - * @param token the token used for the service's payments, including the referral amount + * @param rateToken the token used for the service's payments, including the referral amount * @param referralAmount the amount which the referrer will receive if a proposal is validated by un user which was referred */ struct Service { @@ -56,7 +56,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU string dataUri; uint256 transactionId; uint256 platformId; - address token; + address rateToken; uint256 referralAmount; } @@ -64,8 +64,8 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @notice Proposal information struct * @param status the current status of a service * @param ownerId the talentLayerId of the seller - * @param token the token choose for the payment - * @param amount the amount of token chosen + * @param rateToken the token choose for the payment + * @param rateAmount the amount of token chosen * @param dataUri token Id to IPFS URI mapping * @param expirationDate the timeout for the proposal * @param referrerId the id of the referrer (Zero if no referrer) @@ -73,8 +73,8 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU struct Proposal { ProposalStatus status; uint256 ownerId; - address token; - uint256 amount; + address rateToken; + uint256 rateAmount; uint256 platformId; string dataUri; uint256 expirationDate; @@ -99,7 +99,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param ownerId the talentLayerId of the buyer * @param platformId platform ID on which the Service token was minted * @param dataUri token Id to IPFS URI mapping - * @param token the token used for the service's payments, including the referral amount + * @param rateToken the token used for the service's payments, including the referral amount * @param referralAmount the amount which the referrer will receive if a proposal is validated by un user which was referred */ event ServiceCreated( @@ -107,7 +107,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU uint256 ownerId, uint256 platformId, string dataUri, - address token, + address rateToken, uint256 referralAmount ); @@ -117,13 +117,6 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU */ event ServiceCancelled(uint256 id); - /** - * @notice Emit when Cid is updated for a Service - * @param id The service ID - * @param dataUri New service Data URI - */ - event ServiceDetailedUpdated(uint256 indexed id, string dataUri); - /** * @notice Emit when data is updated for a Service * @param id The service ID @@ -322,7 +315,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param _platformId platform ID on which the Service token was created * @param _dataUri IPFS URI of the offchain data of the service * @param _signature optional platform signature to allow the operation - * @param _token token address to be used for the service's payments + * @param _rateToken token address to be used for the service's payments * @param _referralAmount the amount which the referrer will receive if a proposal is validated by un user which was referred */ function createService( @@ -330,10 +323,10 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU uint256 _platformId, string calldata _dataUri, bytes calldata _signature, - address _token, + address _rateToken, uint256 _referralAmount ) public payable onlyOwnerOrDelegate(_profileId) returns (uint256) { - _validateService(_profileId, _platformId, _dataUri, _signature, _token); + _validateService(_profileId, _platformId, _dataUri, _signature, _rateToken); uint256 id = nextServiceId; nextServiceId++; @@ -343,7 +336,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU service.ownerId = _profileId; service.dataUri = _dataUri; service.platformId = _platformId; - service.token = _token; + service.rateToken = _rateToken; service.referralAmount = _referralAmount; if (serviceNonce[_profileId] == 0 && proposalNonce[_profileId] == 0) { @@ -351,7 +344,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU } serviceNonce[_profileId]++; - emit ServiceCreated(id, _profileId, _platformId, _dataUri, _token, _referralAmount); + emit ServiceCreated(id, _profileId, _platformId, _dataUri, _rateToken, _referralAmount); return id; } @@ -360,7 +353,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @notice Allows an seller to propose his service for a service * @param _profileId The TalentLayer ID of the user owner of the proposal * @param _serviceId The service linked to the new proposal - * @param _amount the amount of token chosen + * @param _rateAmount the amount of token chosen * @param _dataUri token Id to IPFS URI mapping * @param _platformId platform ID from where the proposal is created * @param _expirationDate the time before the proposal is automatically validated @@ -370,7 +363,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU function createProposal( uint256 _profileId, uint256 _serviceId, - uint256 _amount, + uint256 _rateAmount, uint256 _platformId, string calldata _dataUri, uint256 _expirationDate, @@ -378,13 +371,13 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU uint256 _referrerId ) public payable onlyOwnerOrDelegate(_profileId) { Service storage service = services[_serviceId]; - _validateProposal(_profileId, _serviceId, _amount, _platformId, _dataUri, _signature, _referrerId); + _validateProposal(_profileId, _serviceId, _rateAmount, _platformId, _dataUri, _signature, _referrerId); proposals[_serviceId][_profileId] = Proposal({ status: ProposalStatus.Pending, ownerId: _profileId, - token: service.token, - amount: _amount, + rateToken: service.rateToken, + rateAmount: _rateAmount, platformId: _platformId, dataUri: _dataUri, expirationDate: _expirationDate, @@ -401,7 +394,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU _profileId, _dataUri, ProposalStatus.Pending, - _amount, + _rateAmount, _platformId, _expirationDate, _referrerId @@ -412,7 +405,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @notice Allows the owner to update his own proposal for a given service * @param _profileId The TalentLayer ID of the user * @param _serviceId The service linked to the new proposal - * @param _amount the amount of token chosen + * @param _rateAmount the amount of token chosen * @param _dataUri token Id to IPFS URI mapping * @param _expirationDate the time before the proposal is automatically validated * @param _referrerId the id of the referrer (Zero if no referrer) @@ -420,7 +413,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU function updateProposal( uint256 _profileId, uint256 _serviceId, - uint256 _amount, + uint256 _rateAmount, string calldata _dataUri, uint256 _expirationDate, uint256 _referrerId @@ -431,18 +424,18 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU require(proposal.ownerId == _profileId, "Not the owner"); require(bytes(_dataUri).length == 46, "Invalid cid"); require(proposal.status != ProposalStatus.Validated, "Already validated"); - require(_amount >= allowedTokenList[service.token].minimumTransactionAmount, "Amount too low"); + require(_rateAmount >= allowedTokenList[service.rateToken].minimumTransactionAmount, "Amount too low"); if (_referrerId != 0) { tlId.isValid(_referrerId); } - proposal.amount = _amount; + proposal.rateAmount = _rateAmount; proposal.dataUri = _dataUri; proposal.expirationDate = _expirationDate; proposal.referrerId = _referrerId; - emit ProposalUpdated(_serviceId, _profileId, _dataUri, _amount, _expirationDate, _referrerId); + emit ProposalUpdated(_serviceId, _profileId, _dataUri, _rateAmount, _expirationDate, _referrerId); } /** @@ -495,7 +488,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU Service storage service = services[_serviceId]; Proposal storage proposal = proposals[_serviceId][service.acceptedProposalId]; - uint256 releasedPercentage = (_releasedAmount * 100) / proposal.amount; + uint256 releasedPercentage = (_releasedAmount * 100) / proposal.rateAmount; if (releasedPercentage >= minCompletionPercentage) { service.status = Status.Finished; } else { @@ -586,18 +579,19 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param _platformId platform ID on which the Service was created * @param _dataUri token Id to IPFS URI mapping * @param _signature platform signature to allow the operation + * @param _rateToken token address to be validated */ function _validateService( uint256 _profileId, uint256 _platformId, string calldata _dataUri, bytes calldata _signature, - address _token + address _rateToken ) private view { uint256 servicePostingFee = talentLayerPlatformIdContract.getServicePostingFee(_platformId); require(msg.value == servicePostingFee, "Non-matching funds"); require(bytes(_dataUri).length == 46, "Invalid cid"); - require(allowedTokenList[_token].isWhitelisted, "Token not allowed"); + require(allowedTokenList[_rateToken].isWhitelisted, "Token not allowed"); address platformSigner = talentLayerPlatformIdContract.getSigner(_platformId); if (platformSigner != address(0)) { @@ -612,10 +606,11 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @notice Validate a new proposal * @param _profileId The TalentLayer ID of the user * @param _serviceId The service linked to the new proposal - * @param _amount the amount of token chosen - * @param _platformId platform ID on which the Proposal was created - * @param _dataUri token Id to IPFS URI mapping - * @param _signature platform signature to allow the operation + * @param _amount The amount of token chosen + * @param _platformId Platform ID on which the Proposal was created + * @param _dataUri Token Id to IPFS URI mapping + * @param _signature Platform signature to allow the operation + * @param _referrerId The TalentLayer ID of the referrer */ function _validateProposal( uint256 _profileId, @@ -631,7 +626,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU Service storage service = services[_serviceId]; require( - _amount + service.referralAmount >= allowedTokenList[service.token].minimumTransactionAmount, + _amount + service.referralAmount >= allowedTokenList[service.rateToken].minimumTransactionAmount, "Amount too low" ); require(service.status == Status.Opened, "Service not opened"); diff --git a/contracts/interfaces/ITalentLayerService.sol b/contracts/interfaces/ITalentLayerService.sol index 97e3e25d..2fda7fbc 100644 --- a/contracts/interfaces/ITalentLayerService.sol +++ b/contracts/interfaces/ITalentLayerService.sol @@ -26,15 +26,15 @@ interface ITalentLayerService { string dataUri; uint256 transactionId; uint256 platformId; - address token; + address rateToken; uint256 referralAmount; } struct Proposal { ProposalStatus status; uint256 ownerId; - address token; - uint256 amount; + address rateToken; + uint256 rateAmount; uint256 platformId; string dataUri; uint256 expirationDate; @@ -55,14 +55,14 @@ interface ITalentLayerService { uint256 _platformId, string calldata _dataUri, bytes calldata _signature, - address _token, + address _rateToken, uint256 _referralAmount ) external returns (uint256); function createProposal( uint256 _profileId, uint256 _serviceId, - uint256 _amount, + uint256 _rateAmount, uint256 _platformId, string calldata _dataUri, uint256 _expirationDate, @@ -75,7 +75,7 @@ interface ITalentLayerService { function updateProposal( uint256 _profileId, uint256 _serviceId, - uint256 _amount, + uint256 _rateAmount, string calldata _dataUri, uint256 _expirationDate, uint256 _referrerId From 0b5a47900e90159235b8a4ea442c463e8a313179 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Thu, 15 Jun 2023 10:31:12 +0200 Subject: [PATCH 70/99] Update tests Signed-off-by: Quentin D.C --- test/batch/disputeResolution.ts | 2 +- test/batch/fullWorkflow.ts | 40 ++++++++++++++++----------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/test/batch/disputeResolution.ts b/test/batch/disputeResolution.ts index 4695224b..640183c2 100644 --- a/test/batch/disputeResolution.ts +++ b/test/batch/disputeResolution.ts @@ -160,7 +160,7 @@ async function createTransaction( // we need to retreive the Bob proposal dataUri const proposal = await talentLayerService.proposals(serviceId, bobTlId) - const value = proposal.token === ethAddress ? totalTransactionAmount : 0 + const value = proposal.rateToken === ethAddress ? totalTransactionAmount : 0 let tx: ContractTransaction tokenAddress === ethAddress diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index e1fd3670..d71a671e 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -876,7 +876,7 @@ describe('TalentLayer protocol global testing', function () { expect(service6Data.status).to.be.equal(ServiceStatus.Opened) expect(service6Data.ownerId).to.be.equal(aliceTlId) - expect(service6Data.token).to.be.equal(ethers.constants.AddressZero) + expect(service6Data.rateToken).to.be.equal(ethers.constants.AddressZero) expect(service6Data.dataUri).to.be.equal(cid) expect(service6Data.platformId).to.be.equal(1) expect(service6Data.referralAmount).to.be.equal(referralAmount) @@ -900,7 +900,7 @@ describe('TalentLayer protocol global testing', function () { expect(service7Data.status).to.be.equal(ServiceStatus.Opened) expect(service7Data.ownerId).to.be.equal(aliceTlId) - expect(service7Data.token).to.be.equal(token.address) + expect(service7Data.rateToken).to.be.equal(token.address) expect(service7Data.dataUri).to.be.equal(cid) expect(service7Data.platformId).to.be.equal(1) expect(service7Data.referralAmount).to.be.equal(referralAmount) @@ -1087,8 +1087,8 @@ describe('TalentLayer protocol global testing', function () { // Proposal data check after the proposal // @dev: token field not used any more - expect(proposalDataAfter.token).to.be.equal(serviceData.token) - expect(proposalDataAfter.amount.toString()).to.be.equal('15') + expect(proposalDataAfter.rateToken).to.be.equal(serviceData.rateToken) + expect(proposalDataAfter.rateAmount.toString()).to.be.equal('15') expect(proposalDataAfter.dataUri).to.be.equal(cid2) expect(proposalDataAfter.platformId).to.be.equal(alicePlatformId) expect(proposalDataAfter.expirationDate).to.be.equal(proposalExpirationDate) @@ -1096,7 +1096,7 @@ describe('TalentLayer protocol global testing', function () { expect(proposalDataAfter.status.toString()).to.be.equal('0') expect(proposalDataAfter.referrerId).to.be.equal(0) expect(tx) - .to.emit(talentLayerService, 'ProposalCreatedWithoutToken') + .to.emit(talentLayerService, 'ProposalCreatedWithoutrateToken') .withArgs(1, bobTlId, cid2, 'Pending', 15, alicePlatformId, proposalExpirationDate, 0) }) @@ -1160,8 +1160,8 @@ describe('TalentLayer protocol global testing', function () { // Proposal data check after the proposal // @dev: token field not used any more - expect(proposalDataAfter.token).to.be.equal(serviceData.token) - expect(proposalDataAfter.amount.toString()).to.be.equal('2000000') + expect(proposalDataAfter.rateToken).to.be.equal(serviceData.rateToken) + expect(proposalDataAfter.rateAmount.toString()).to.be.equal('2000000') expect(proposalDataAfter.dataUri).to.be.equal(cid2) expect(proposalDataAfter.platformId).to.be.equal(alicePlatformId) expect(proposalDataAfter.expirationDate).to.be.equal(proposalExpirationDate) @@ -1218,8 +1218,8 @@ describe('TalentLayer protocol global testing', function () { // Proposal data check after the proposal // @dev: token field not used any more - expect(proposalDataAfter.token).to.be.equal(serviceData.token) - expect(proposalDataAfter.amount.toString()).to.be.equal('2000000') + expect(proposalDataAfter.rateToken).to.be.equal(serviceData.rateToken) + expect(proposalDataAfter.rateAmount.toString()).to.be.equal('2000000') expect(proposalDataAfter.dataUri).to.be.equal(cid2) expect(proposalDataAfter.platformId).to.be.equal(alicePlatformId) expect(proposalDataAfter.expirationDate).to.be.equal(proposalExpirationDate) @@ -1315,7 +1315,7 @@ describe('TalentLayer protocol global testing', function () { it('Bob can update his first proposal ', async function () { const proposalDataBefore = await talentLayerService.getProposal(1, bobTlId) - expect(proposalDataBefore.amount.toString()).to.be.equal('15') + expect(proposalDataBefore.rateAmount.toString()).to.be.equal('15') const serviceData = await talentLayerService.services(1) @@ -1327,9 +1327,9 @@ describe('TalentLayer protocol global testing', function () { expect(tx) .to.emit(talentLayerService, 'ProposalUpdatedWithoutToken') .withArgs(1, bobTlId, cid, 18, proposalExpirationDate) - expect(proposalDataAfter.amount.toString()).to.be.equal('18') + expect(proposalDataAfter.rateAmount.toString()).to.be.equal('18') expect(proposalDataAfter.expirationDate).to.be.equal(proposalExpirationDate) - expect(proposalDataAfter.token.toString()).to.be.equal(serviceData.token) + expect(proposalDataAfter.rateToken.toString()).to.be.equal(serviceData.rateToken) expect(proposalDataAfter.dataUri).to.be.equal(cid) expect(proposalDataAfter.referrerId).to.be.equal(aliceTlId) }) @@ -1607,12 +1607,12 @@ describe('TalentLayer protocol global testing', function () { const originValidatedProposalFeeRate = alicePlatformData.originValidatedProposalFeeRate const referralAmount = service.referralAmount - const totalAmountWithReferral = proposal.amount + const totalAmountWithReferral = proposal.rateAmount .add( - proposal.amount + proposal.rateAmount .mul(protocolEscrowFeeRate) - .add(proposal.amount.mul(originServiceFeeRate)) - .add(proposal.amount.mul(originValidatedProposalFeeRate)) + .add(proposal.rateAmount.mul(originServiceFeeRate)) + .add(proposal.rateAmount.mul(originValidatedProposalFeeRate)) .div(FEE_DIVIDER), ) .add(referralAmount) @@ -2173,12 +2173,12 @@ describe('TalentLayer protocol global testing', function () { const originValidatedProposalFeeRate = alicePlatformData.originValidatedProposalFeeRate const referralAmount = service.referralAmount - const totalAmountWithReferral = proposal.amount + const totalAmountWithReferral = proposal.rateAmount .add( - proposal.amount + proposal.rateAmount .mul(protocolEscrowFeeRate) - .add(proposal.amount.mul(originServiceFeeRate)) - .add(proposal.amount.mul(originValidatedProposalFeeRate)) + .add(proposal.rateAmount.mul(originServiceFeeRate)) + .add(proposal.rateAmount.mul(originValidatedProposalFeeRate)) .div(FEE_DIVIDER), ) .add(referralAmount) From dca99047d667c96c206c726be3ba367ed6749cf3 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Thu, 15 Jun 2023 10:39:57 +0200 Subject: [PATCH 71/99] Moved new mapping to bottom of variables sections Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index 827dd3d8..3a4ba650 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -288,14 +288,6 @@ contract TalentLayerEscrow is */ mapping(uint256 => mapping(address => uint256)) private platformIdToTokenToBalance; - /** - * @notice Mapping from referrerId to Token address to Token Balance - * Represents the amount of ETH or token present on this contract which - * belongs to a referrer and can be withdrawn. - * @dev address(0) is reserved to ETH balance - */ - mapping(uint256 => mapping(address => uint256)) private referrerIdToTokenToBalance; - /** * @notice Instance of TalentLayerService.sol */ @@ -356,6 +348,14 @@ contract TalentLayerEscrow is */ CountersUpgradeable.Counter private nextTransactionId; + /** + * @notice Mapping from referrerId to Token address to Token Balance + * Represents the amount of ETH or token present on this contract which + * belongs to a referrer and can be withdrawn. + * @dev address(0) is reserved to ETH balance + */ + mapping(uint256 => mapping(address => uint256)) private referrerIdToTokenToBalance; + /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); From 688858a50bd8536eab5bf1a05d23b5d27d4bf977 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Thu, 15 Jun 2023 22:18:59 +0200 Subject: [PATCH 72/99] Modified new events names Signed-off-by: Quentin D.C --- contracts/TalentLayerService.sol | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/contracts/TalentLayerService.sol b/contracts/TalentLayerService.sol index cbed450b..d2e5a21e 100644 --- a/contracts/TalentLayerService.sol +++ b/contracts/TalentLayerService.sol @@ -102,8 +102,8 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param rateToken the token used for the service's payments, including the referral amount * @param referralAmount the amount which the referrer will receive if a proposal is validated by un user which was referred */ - event ServiceCreated( - uint256 indexed id, + event ServiceCreatedWithReferral( + uint256 id, uint256 ownerId, uint256 platformId, string dataUri, @@ -123,7 +123,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param dataUri New service Data URI * @param referralAmount New referral amount */ - event ServiceUpdated(uint256 indexed id, string dataUri, uint256 referralAmount); + event ServiceUpdated(uint256 id, string dataUri, uint256 referralAmount); /** * @notice Emitted after a new proposal is created @@ -136,7 +136,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param expirationDate the timeout for the proposal * @param referrerId the id of the referrer (Zero if no referrer) */ - event ProposalCreated( + event ProposalCreatedWithReferrer( uint256 serviceId, uint256 ownerId, string dataUri, @@ -156,7 +156,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param expirationDate the timeout for the proposal * @param referrerId the id of the referrer (Zero if no referrer) */ - event ProposalUpdated( + event ProposalUpdatedWithReferrer( uint256 serviceId, uint256 ownerId, string dataUri, @@ -344,7 +344,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU } serviceNonce[_profileId]++; - emit ServiceCreated(id, _profileId, _platformId, _dataUri, _rateToken, _referralAmount); + emit ServiceCreatedWithReferral(id, _profileId, _platformId, _dataUri, _rateToken, _referralAmount); return id; } @@ -389,7 +389,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU } proposalNonce[_profileId]++; - emit ProposalCreated( + emit ProposalCreatedWithReferrer( _serviceId, _profileId, _dataUri, @@ -435,7 +435,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU proposal.expirationDate = _expirationDate; proposal.referrerId = _referrerId; - emit ProposalUpdated(_serviceId, _profileId, _dataUri, _rateAmount, _expirationDate, _referrerId); + emit ProposalUpdatedWithReferrer(_serviceId, _profileId, _dataUri, _rateAmount, _expirationDate, _referrerId); } /** From 30b3254b26fcc32be30a8ff3fa780906336dd99b Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Fri, 16 Jun 2023 13:06:26 +0200 Subject: [PATCH 73/99] Moved a function in Service contract Signed-off-by: Quentin D.C --- contracts/TalentLayerService.sol | 50 ++++++++++++++++---------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/contracts/TalentLayerService.sol b/contracts/TalentLayerService.sol index d2e5a21e..d840bb5e 100644 --- a/contracts/TalentLayerService.sol +++ b/contracts/TalentLayerService.sol @@ -349,6 +349,31 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU return id; } + /** + * @notice Update Service URI data + * @param _profileId The TalentLayer ID of the user, owner of the service + * @param _serviceId, Service ID to update + * @param _referralAmount, New referral amount + * @param _dataUri New IPFS URI + */ + function updateService( + uint256 _profileId, + uint256 _serviceId, + uint256 _referralAmount, + string calldata _dataUri + ) public onlyOwnerOrDelegate(_profileId) { + Service storage service = services[_serviceId]; + require(service.ownerId == _profileId, "Not the owner"); + require(service.status == Status.Opened, "status must be opened"); + require(bytes(_dataUri).length == 46, "Invalid cid"); + require(_referralAmount >= service.referralAmount, "Can't reduce referral amount"); + + service.dataUri = _dataUri; + service.referralAmount = _referralAmount; + + emit ServiceUpdated(_serviceId, _dataUri, _referralAmount); + } + /** * @notice Allows an seller to propose his service for a service * @param _profileId The TalentLayer ID of the user owner of the proposal @@ -496,31 +521,6 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU } } - /** - * @notice Update Service URI data - * @param _profileId The TalentLayer ID of the user, owner of the service - * @param _serviceId, Service ID to update - * @param _referralAmount, New referral amount - * @param _dataUri New IPFS URI - */ - function updateService( - uint256 _profileId, - uint256 _serviceId, - uint256 _referralAmount, - string calldata _dataUri - ) public onlyOwnerOrDelegate(_profileId) { - Service storage service = services[_serviceId]; - require(service.ownerId == _profileId, "Not the owner"); - require(service.status == Status.Opened, "status must be opened"); - require(bytes(_dataUri).length == 46, "Invalid cid"); - require(_referralAmount >= service.referralAmount, "Can't reduce referral amount"); - - service.dataUri = _dataUri; - service.referralAmount = _referralAmount; - - emit ServiceUpdated(_serviceId, _dataUri, _referralAmount); - } - /** * @notice Cancel an open Service * @param _profileId The TalentLayer ID of the user, owner of the service From ba6289981ef05de32ed71699bc04062714d6653e Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Fri, 16 Jun 2023 13:06:36 +0200 Subject: [PATCH 74/99] Fixed a bug in escrow contract Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index 3a4ba650..fa08da9d 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -972,8 +972,11 @@ contract TalentLayerEscrow is function _reimburse(uint256 _transactionId, uint256 _amount) private { Transaction storage transaction = transactions[_transactionId]; - //If no referrerId (=0), the referralAmount will always be 0 - uint256 reimbursedReferralAmount = (_amount * transaction.referralAmount) / (transaction.totalAmount); + // If no referrerId (=0), the referralAmount will always be 0 + // @dev: Legacy transactions will have a totalAmount of 0; need to check for that + uint256 reimbursedReferralAmount = transaction.totalAmount != 0 + ? (_amount * transaction.referralAmount) / (transaction.totalAmount) + : 0; uint256 totalReimburseAmount = _calculateTotalWithFees( _amount, From f21c3b2da969ee7df32834c8162c22584e8281ea Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Fri, 16 Jun 2023 17:09:41 +0200 Subject: [PATCH 75/99] Update Service Interface Signed-off-by: Quentin D.C --- contracts/TalentLayerService.sol | 2 +- contracts/interfaces/ITalentLayerService.sol | 28 ++++++++++++++------ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/contracts/TalentLayerService.sol b/contracts/TalentLayerService.sol index d840bb5e..b9ce8301 100644 --- a/contracts/TalentLayerService.sol +++ b/contracts/TalentLayerService.sol @@ -632,7 +632,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU require(service.status == Status.Opened, "Service not opened"); require(service.ownerId != 0, "Service not exist"); require(proposals[_serviceId][_profileId].ownerId != _profileId, "proposal already exist"); - //TODO add test for this ? We keep it or not ? (Good for stats, bad if buyer adds referral amount) + //TODO @Romain: add test for this ? We keep it or not ? (Good for stats, bad if buyer adds referral amount) if (_referrerId != 0) { require(service.referralAmount > 0, "Can't refer someone for this service"); } diff --git a/contracts/interfaces/ITalentLayerService.sol b/contracts/interfaces/ITalentLayerService.sol index 2fda7fbc..dea12dce 100644 --- a/contracts/interfaces/ITalentLayerService.sol +++ b/contracts/interfaces/ITalentLayerService.sol @@ -50,6 +50,8 @@ interface ITalentLayerService { uint256 _proposal ) external view returns (Service memory, Proposal memory); + function isTokenAllowed(address _tokenAddress) external view returns (bool); + function createService( uint256 _profileId, uint256 _platformId, @@ -59,6 +61,13 @@ interface ITalentLayerService { uint256 _referralAmount ) external returns (uint256); + function updateService( + uint256 _profileId, + uint256 _serviceId, + uint256 _referralAmount, + string calldata _dataUri + ) external; + function createProposal( uint256 _profileId, uint256 _serviceId, @@ -70,8 +79,6 @@ interface ITalentLayerService { uint256 _referrerId ) external; - function afterDeposit(uint256 _serviceId, uint256 _proposalId, uint256 _transactionId) external; - function updateProposal( uint256 _profileId, uint256 _serviceId, @@ -81,12 +88,17 @@ interface ITalentLayerService { uint256 _referrerId ) external; - function afterFullPayment(uint256 _serviceId, uint256 _releasedAmount) external; + function afterDeposit(uint256 _serviceId, uint256 _proposalId, uint256 _transactionId) external; - function updateService( - uint256 _profileId, - uint256 _serviceId, - uint256 _referralAmount, - string calldata _dataUri + function updateAllowedTokenList( + address _tokenAddress, + bool _isWhitelisted, + uint256 _minimumTransactionAmount ) external; + + function afterFullPayment(uint256 _serviceId, uint256 _releasedAmount) external; + + function cancelService(uint256 _profileId, uint256 _serviceId) external; + + function updateMinCompletionPercentage(uint256 _minCompletionPercentage) external; } From e1c5143150e54cc64af5c3d2ae45fd6f84b05f59 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Fri, 16 Jun 2023 17:17:19 +0200 Subject: [PATCH 76/99] Update Escrow Interface Signed-off-by: Quentin D.C --- contracts/interfaces/ITalentLayerEscrow.sol | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/contracts/interfaces/ITalentLayerEscrow.sol b/contracts/interfaces/ITalentLayerEscrow.sol index 0788860c..987300ce 100644 --- a/contracts/interfaces/ITalentLayerEscrow.sol +++ b/contracts/interfaces/ITalentLayerEscrow.sol @@ -43,6 +43,8 @@ interface ITalentLayerEscrow { function getClaimableFeeBalance(address _token) external view returns (uint256 balance); + function getClaimableReferralBalance(address _token) external view returns (uint256 balance); + function getTransactionDetails(uint256 _transactionId) external view returns (Transaction memory); function updateProtocolEscrowFeeRate(uint16 _protocolEscrowFeeRate) external; @@ -56,25 +58,23 @@ interface ITalentLayerEscrow { string memory originDataUri ) external payable returns (uint256); - function release(uint256 _transactionId, uint256 _amount) external; - - function reimburse(uint256 _transactionId, uint256 _amount) external; - - function claim(uint256 _platformId, address _tokenAddress) external; + function release(uint256 _profileId, uint256 _transactionId, uint256 _amount) external; - function claimAll(uint256 _platformId) external; + function reimburse(uint256 _profileId, uint256 _transactionId, uint256 _amount) external; function payArbitrationFeeBySender(uint256 _transactionId) external payable; function payArbitrationFeeByReceiver(uint256 _transactionId) external payable; - function timeOutBySender(uint256 _transactionId) external; + function arbitrationFeeTimeout(uint256 _transactionId) external; - function timeOutByReceiver(uint256 _transactionId) external; - - function submitEvidence(uint256 _transactionId, string memory _evidence) external; + function submitEvidence(uint256 _profileId, uint256 _transactionId, string memory _evidence) external; function appeal(uint256 _transactionId) external payable; + function claim(uint256 _platformId, address _tokenAddress) external; + + function claimReferralBalance(uint256 _referrerId, address _tokenAddress) external; + function rule(uint256 _disputeID, uint256 _ruling) external; } From 8805587b3dcafdff9f4d8809a37d726cb97058de Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Fri, 16 Jun 2023 22:13:20 +0200 Subject: [PATCH 77/99] Renamed events Signed-off-by: Quentin D.C --- contracts/TalentLayerService.sol | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/TalentLayerService.sol b/contracts/TalentLayerService.sol index b9ce8301..f21e2f3d 100644 --- a/contracts/TalentLayerService.sol +++ b/contracts/TalentLayerService.sol @@ -102,7 +102,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param rateToken the token used for the service's payments, including the referral amount * @param referralAmount the amount which the referrer will receive if a proposal is validated by un user which was referred */ - event ServiceCreatedWithReferral( + event ServiceCreated( uint256 id, uint256 ownerId, uint256 platformId, @@ -136,7 +136,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param expirationDate the timeout for the proposal * @param referrerId the id of the referrer (Zero if no referrer) */ - event ProposalCreatedWithReferrer( + event ProposalCreated( uint256 serviceId, uint256 ownerId, string dataUri, @@ -156,7 +156,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param expirationDate the timeout for the proposal * @param referrerId the id of the referrer (Zero if no referrer) */ - event ProposalUpdatedWithReferrer( + event ProposalUpdated( uint256 serviceId, uint256 ownerId, string dataUri, @@ -344,7 +344,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU } serviceNonce[_profileId]++; - emit ServiceCreatedWithReferral(id, _profileId, _platformId, _dataUri, _rateToken, _referralAmount); + emit ServiceCreated(id, _profileId, _platformId, _dataUri, _rateToken, _referralAmount); return id; } @@ -414,7 +414,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU } proposalNonce[_profileId]++; - emit ProposalCreatedWithReferrer( + emit ProposalCreated( _serviceId, _profileId, _dataUri, @@ -460,7 +460,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU proposal.expirationDate = _expirationDate; proposal.referrerId = _referrerId; - emit ProposalUpdatedWithReferrer(_serviceId, _profileId, _dataUri, _rateAmount, _expirationDate, _referrerId); + emit ProposalUpdated(_serviceId, _profileId, _dataUri, _rateAmount, _expirationDate, _referrerId); } /** From a74368dbc7e67518ff4a0060948c02c317a4d481 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Fri, 16 Jun 2023 22:27:52 +0200 Subject: [PATCH 78/99] Updated tests with correct tests + args Signed-off-by: Quentin D.C --- test/batch/fullWorkflow.ts | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index d71a671e..698fa3a9 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -792,7 +792,7 @@ describe('TalentLayer protocol global testing', function () { // Alice will create 4 Open services fo the whole unit test process const signature = await getSignatureForService(platformOneOwner, aliceTlId, 0, cid) - await talentLayerService + const tx = await talentLayerService .connect(alice) .createService(aliceTlId, alicePlatformId, cid, signature, token.address, 0, { value: alicePlatformServicePostingFee, @@ -848,6 +848,9 @@ describe('TalentLayer protocol global testing', function () { expect(service1Data.dataUri).to.be.equal(cid) expect(service1Data.platformId).to.be.equal(1) expect(service1Data.referralAmount).to.be.equal(0) + expect(tx) + .to.emit(talentLayerService, 'ServiceCreated') + .withArgs(5, aliceTlId, alicePlatformId, cid, token.address, 0) }) it('Alice the buyer can create a service using ETH with referral', async function () { @@ -872,7 +875,7 @@ describe('TalentLayer protocol global testing', function () { expect(tx) .to.emit(talentLayerService, 'ServiceCreated') - .withArgs(6, aliceTlId, alicePlatformId, cid, token.address, referralAmount) + .withArgs(6, aliceTlId, alicePlatformId, cid, ethers.constants.AddressZero, referralAmount) expect(service6Data.status).to.be.equal(ServiceStatus.Opened) expect(service6Data.ownerId).to.be.equal(aliceTlId) @@ -1086,7 +1089,6 @@ describe('TalentLayer protocol global testing', function () { expect(serviceData.ownerId).to.be.equal(aliceTlId) // Proposal data check after the proposal - // @dev: token field not used any more expect(proposalDataAfter.rateToken).to.be.equal(serviceData.rateToken) expect(proposalDataAfter.rateAmount.toString()).to.be.equal('15') expect(proposalDataAfter.dataUri).to.be.equal(cid2) @@ -1096,7 +1098,7 @@ describe('TalentLayer protocol global testing', function () { expect(proposalDataAfter.status.toString()).to.be.equal('0') expect(proposalDataAfter.referrerId).to.be.equal(0) expect(tx) - .to.emit(talentLayerService, 'ProposalCreatedWithoutrateToken') + .to.emit(talentLayerService, 'ProposalCreated') .withArgs(1, bobTlId, cid2, 'Pending', 15, alicePlatformId, proposalExpirationDate, 0) }) @@ -1169,16 +1171,16 @@ describe('TalentLayer protocol global testing', function () { expect(proposalDataAfter.status.toString()).to.be.equal('0') expect(proposalDataAfter.referrerId.toString()).to.be.equal(bobTlId.toString()) expect(tx) - .to.emit(talentLayerService, 'ProposalCreatedWithoutToken') + .to.emit(talentLayerService, 'ProposalCreated') .withArgs( 6, - bobTlId, + carolTlId, cid2, 'Pending', - 15, + 2000000, alicePlatformId, proposalExpirationDate, - carolTlId, + bob, ) }) @@ -1227,16 +1229,16 @@ describe('TalentLayer protocol global testing', function () { expect(proposalDataAfter.status.toString()).to.be.equal('0') expect(proposalDataAfter.referrerId.toString()).to.be.equal(bobTlId.toString()) expect(tx) - .to.emit(talentLayerService, 'ProposalCreatedWithoutToken') + .to.emit(talentLayerService, 'ProposalCreated') .withArgs( 7, - bobTlId, + carolTlId, cid2, 'Pending', - 15, + 2000000, alicePlatformId, proposalExpirationDate, - carolTlId, + bobTlId, ) }) @@ -1325,7 +1327,7 @@ describe('TalentLayer protocol global testing', function () { const proposalDataAfter = await talentLayerService.getProposal(1, bobTlId) expect(tx) - .to.emit(talentLayerService, 'ProposalUpdatedWithoutToken') + .to.emit(talentLayerService, 'ProposalUpdated') .withArgs(1, bobTlId, cid, 18, proposalExpirationDate) expect(proposalDataAfter.rateAmount.toString()).to.be.equal('18') expect(proposalDataAfter.expirationDate).to.be.equal(proposalExpirationDate) From a3e49af1494faefa1ecd1ceb354bb972d1d7099f Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Tue, 20 Jun 2023 09:10:57 +0200 Subject: [PATCH 79/99] Removed isValid check for referral balance view Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index fa08da9d..cd3efee9 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -425,7 +425,6 @@ contract TalentLayerEscrow is */ function getClaimableReferralBalance(address _token) external view returns (uint256 balance) { uint256 referrerId = talentLayerIdContract.ids(_msgSender()); - talentLayerIdContract.isValid(referrerId); return referrerIdToTokenToBalance[referrerId][_token]; } From 4d60193a9d9276b02de737c2a6bfbcc2c8b42902 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Tue, 20 Jun 2023 09:14:37 +0200 Subject: [PATCH 80/99] amount => rateAmount Signed-off-by: Quentin D.C --- contracts/TalentLayerService.sol | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/contracts/TalentLayerService.sol b/contracts/TalentLayerService.sol index f21e2f3d..7ea22e0f 100644 --- a/contracts/TalentLayerService.sol +++ b/contracts/TalentLayerService.sol @@ -131,7 +131,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param ownerId The talentLayerId of the seller who made the proposal * @param dataUri token Id to IPFS URI mapping * @param status proposal status - * @param amount the amount of token chosen + * @param rateAmount the amount of token chosen * @param platformId the platform ID on which the proposal was created * @param expirationDate the timeout for the proposal * @param referrerId the id of the referrer (Zero if no referrer) @@ -141,7 +141,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU uint256 ownerId, string dataUri, ProposalStatus status, - uint256 amount, + uint256 rateAmount, uint256 platformId, uint256 expirationDate, uint256 referrerId @@ -152,7 +152,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param serviceId The service id * @param ownerId The talentLayerId of the seller who made the proposal * @param dataUri token Id to IPFS URI mapping - * @param amount the amount of token chosen + * @param rateAmount the amount of token chosen * @param expirationDate the timeout for the proposal * @param referrerId the id of the referrer (Zero if no referrer) */ @@ -160,7 +160,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU uint256 serviceId, uint256 ownerId, string dataUri, - uint256 amount, + uint256 rateAmount, uint256 expirationDate, uint256 referrerId ); @@ -606,7 +606,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @notice Validate a new proposal * @param _profileId The TalentLayer ID of the user * @param _serviceId The service linked to the new proposal - * @param _amount The amount of token chosen + * @param _rateAmount The amount of token chosen * @param _platformId Platform ID on which the Proposal was created * @param _dataUri Token Id to IPFS URI mapping * @param _signature Platform signature to allow the operation @@ -615,7 +615,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU function _validateProposal( uint256 _profileId, uint256 _serviceId, - uint256 _amount, + uint256 _rateAmount, uint256 _platformId, string calldata _dataUri, bytes calldata _signature, @@ -626,7 +626,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU Service storage service = services[_serviceId]; require( - _amount + service.referralAmount >= allowedTokenList[service.rateToken].minimumTransactionAmount, + _rateAmount + service.referralAmount >= allowedTokenList[service.rateToken].minimumTransactionAmount, "Amount too low" ); require(service.status == Status.Opened, "Service not opened"); From 8263d236f94bacc55d8b19dd1c727cd9cfff4e9b Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Tue, 20 Jun 2023 09:14:51 +0200 Subject: [PATCH 81/99] Remove require statement Signed-off-by: Quentin D.C --- contracts/TalentLayerService.sol | 4 ---- 1 file changed, 4 deletions(-) diff --git a/contracts/TalentLayerService.sol b/contracts/TalentLayerService.sol index 7ea22e0f..7c0a1188 100644 --- a/contracts/TalentLayerService.sol +++ b/contracts/TalentLayerService.sol @@ -632,10 +632,6 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU require(service.status == Status.Opened, "Service not opened"); require(service.ownerId != 0, "Service not exist"); require(proposals[_serviceId][_profileId].ownerId != _profileId, "proposal already exist"); - //TODO @Romain: add test for this ? We keep it or not ? (Good for stats, bad if buyer adds referral amount) - if (_referrerId != 0) { - require(service.referralAmount > 0, "Can't refer someone for this service"); - } require(service.ownerId != _profileId, "can't create for your own service"); require(bytes(_dataUri).length == 46, "Invalid cid"); From 6c2113c27079ebbfbe9ecb0bc4b9abf80c3707fa Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Tue, 20 Jun 2023 19:10:47 +0200 Subject: [PATCH 82/99] Added deploy script for V1 upgrade test Signed-off-by: Quentin D.C --- test/utils/deploy.ts | 92 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) diff --git a/test/utils/deploy.ts b/test/utils/deploy.ts index 05f2308d..3eab7a6a 100644 --- a/test/utils/deploy.ts +++ b/test/utils/deploy.ts @@ -5,9 +5,11 @@ import { SimpleERC20, TalentLayerArbitrator, TalentLayerEscrow, + TalentLayerEscrowV1, TalentLayerID, TalentLayerPlatformID, TalentLayerReview, + TalentLayerServiceV1, } from '../../typechain-types' /** @@ -40,7 +42,7 @@ export async function deploy( let talentLayerID = await upgrades.deployProxy(TalentLayerID, talentLayerIDArgs) if (applyUpgrade) { - const TalentLayerIDV2 = await ethers.getContractFactory('TalentLayerIDV2') + const TalentLayerIDV2 = await ethers.getContractFactory('TalentLayerID') talentLayerID = await upgrades.upgradeProxy(talentLayerID.address, TalentLayerIDV2) } @@ -100,3 +102,91 @@ export async function deploy( simpleERC20, ] } +export async function deployForV1(): Promise< + [ + TalentLayerID, + TalentLayerPlatformID, + TalentLayerEscrowV1, + TalentLayerArbitrator, + TalentLayerServiceV1, + TalentLayerReview, + SimpleERC20, + ] +> { + const chainId = network.config.chainId ? network.config.chainId : Network.LOCAL + const networkConfig: NetworkConfig = getConfig(chainId) + + // Deploy PlatformId + const TalentLayerPlatformID = await ethers.getContractFactory('TalentLayerPlatformID') + const talentLayerPlatformID = await upgrades.deployProxy(TalentLayerPlatformID) + + // Deploy TalentLayerID + const TalentLayerID = await ethers.getContractFactory('TalentLayerID') + const talentLayerIDArgs: [string] = [talentLayerPlatformID.address] + const talentLayerID = await upgrades.deployProxy(TalentLayerID, talentLayerIDArgs) + + // Deploy TalentLayerService + const TalentLayerService = await ethers.getContractFactory('TalentLayerServiceV1') + const talentLayerServiceArgs: [string, string] = [ + talentLayerID.address, + talentLayerPlatformID.address, + ] + const talentLayerService = await upgrades.deployProxy(TalentLayerService, talentLayerServiceArgs) + + // Deploy TalentLayerArbitrator + const TalentLayerArbitrator = await ethers.getContractFactory('TalentLayerArbitrator') + const talentLayerArbitrator = await TalentLayerArbitrator.deploy(talentLayerPlatformID.address) + + // Deploy TalentLayerEscrow and escrow role on TalentLayerService + const TalentLayerEscrow = await ethers.getContractFactory('TalentLayerEscrowV1') + const TalentLayerEscrowArgs: [string, string, string, string | undefined] = [ + talentLayerService.address, + talentLayerID.address, + talentLayerPlatformID.address, + networkConfig.multisigAddressList.fee, + ] + const talentLayerEscrow = await upgrades.deployProxy(TalentLayerEscrow, TalentLayerEscrowArgs) + const escrowRole = await talentLayerService.ESCROW_ROLE() + await talentLayerService.grantRole(escrowRole, talentLayerEscrow.address) + + // Deploy TalentLayerReview + const TalentLayerReview = await ethers.getContractFactory('TalentLayerReview') + const talentLayerReviewArgs: [string, string] = [ + talentLayerID.address, + talentLayerService.address, + ] + const talentLayerReview = await upgrades.deployProxy(TalentLayerReview, talentLayerReviewArgs) + + // Deploy SimpleERC20 Token + const SimpleERC20 = await ethers.getContractFactory('SimpleERC20') + const simpleERC20 = await SimpleERC20.deploy() + + return [ + talentLayerID as TalentLayerID, + talentLayerPlatformID as TalentLayerPlatformID, + talentLayerEscrow as TalentLayerEscrowV1, + talentLayerArbitrator, + talentLayerService as TalentLayerServiceV1, + talentLayerReview as TalentLayerReview, + simpleERC20, + ] +} + +export const upgradeServiceV1 = async (talentLayerServiceAddress: string) => { + const talentLayerServiceUpgrade = await ethers.getContractFactory('TalentLayerService') + const talentLayerService = await upgrades.upgradeProxy( + talentLayerServiceAddress, + talentLayerServiceUpgrade, + ) + + return talentLayerService as TalentLayerService +} + +export const upgradeEscrowV1 = async (talentLayerEscrowAddress: string) => { + const talentLayerEscrowUpgrade = await ethers.getContractFactory('TalentLayerEscrow') + const talentLayerEscrow = await upgrades.upgradeProxy( + talentLayerEscrowAddress, + talentLayerEscrowUpgrade, + ) + return talentLayerEscrow as TalentLayerEscrow +} From fd2022c43051c5824f00dc6f79c5d8a4614e943d Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Tue, 20 Jun 2023 19:11:09 +0200 Subject: [PATCH 83/99] First draft on V1 migration test Signed-off-by: Quentin D.C --- test/batch/upgrades/referral.ts | 370 ++++++++++++++++++++++++++++++++ 1 file changed, 370 insertions(+) create mode 100644 test/batch/upgrades/referral.ts diff --git a/test/batch/upgrades/referral.ts b/test/batch/upgrades/referral.ts new file mode 100644 index 00000000..7f42c91c --- /dev/null +++ b/test/batch/upgrades/referral.ts @@ -0,0 +1,370 @@ +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/dist/src/signer-with-address' +import { + SimpleERC20, + TalentLayerArbitrator, + TalentLayerEscrow, + TalentLayerEscrowV1, + TalentLayerID, + TalentLayerPlatformID, + TalentLayerReview, + TalentLayerService, + TalentLayerServiceV1, +} from '../../../typechain-types' +import { NetworkConfig } from '../../../networkConfig' +import { ethers } from 'hardhat' +import { deployForV1, upgradeEscrowV1, upgradeServiceV1 } from '../../utils/deploy' +import { expect } from 'chai' +import { + cid, + metaEvidenceCid, + minTokenWhitelistTransactionAmount, + MintStatus, + proposalExpirationDate, +} from '../../utils/constant' +import { Contract } from 'ethers' + +const aliceTlId = 1 +const bobTlId = 2 +const carolTlId = 3 +const daveTlId = 4 + +const alicePlatformId = 1 + +const rateAmount = 200000 + +const FEE_DIVIDER = 10000 + +// @dev: We are not testing signatures here, so we can use a fake signature +const fakeSignature = + '0xea53f5cd3f7db698f2fdd38909c58fbd41fe35b54d5b0d6acc3b05555bae1f01795b86ea1d65d8c76954fd6cefd5c59c9c57274966a071be1ee3b783a123ff961b' + +const alicePlatformProposalPostingFee = 0 +describe('TalentLayer protocol global testing', function () { + let deployer: SignerWithAddress, + alice: SignerWithAddress, + bob: SignerWithAddress, + carol: SignerWithAddress, + dave: SignerWithAddress, + talentLayerServiceV1: TalentLayerServiceV1, + talentLayerService: TalentLayerService, + talentLayerID: TalentLayerID, + talentLayerPlatformID: TalentLayerPlatformID, + talentLayerReview: TalentLayerReview, + talentLayerEscrowV1: TalentLayerEscrowV1, + talentLayerEscrow: TalentLayerEscrow, + talentLayerArbitrator: TalentLayerArbitrator, + token: SimpleERC20, + platformName: string, + platformId: string, + mintFee: number, + networkConfig: NetworkConfig, + chainId: number + + const nonListedtoken = '0x6b175474e89094c44da98b954eedeac495271d0f' + const referralAmount = 20000 + + before(async function () { + // Get the Signers + ;[deployer, alice, bob, carol, dave] = await ethers.getSigners() + ;[ + talentLayerID, + talentLayerPlatformID, + talentLayerEscrowV1, + talentLayerArbitrator, + talentLayerServiceV1, + talentLayerReview, + token, + ] = await deployForV1() + + // Grant Platform Id Mint role to Deployer + const mintRole = await talentLayerPlatformID.MINT_ROLE() + await talentLayerPlatformID.connect(deployer).grantRole(mintRole, deployer.address) + + // we first check the actual minting status (should be ONLY_WHITELIST ) + const mintingStatus = await talentLayerPlatformID.connect(deployer).mintStatus() + expect(mintingStatus).to.be.equal(1) + // then we whitelist the deployer and Alice to mint a PlatformId for someone + await talentLayerPlatformID.connect(deployer).whitelistUser(deployer.address) + // we check if the deployer is well whitelisted + const deployerWhitelisted = await talentLayerPlatformID.whitelist(deployer.address) + expect(deployerWhitelisted).to.be.equal(true) + + // Deployer mints Platform Id for Alice + platformName = 'rac00n-corp' + await talentLayerPlatformID.connect(deployer).mintForAddress(platformName, alice.address) + mintFee = 100 + + const allowedTokenList = ['0x0000000000000000000000000000000000000000', token.address] + + // Deployer whitelists a list of authorized tokens + for (const tokenAddress of allowedTokenList) { + await talentLayerServiceV1 + .connect(deployer) + .updateAllowedTokenList(tokenAddress, true, minTokenWhitelistTransactionAmount) + } + + // Disable whitelist for reserved handles + await talentLayerID.connect(deployer).updateMintStatus(MintStatus.PUBLIC) + + // Set service contract address on ID contract + await talentLayerID.connect(deployer).setIsServiceContract(talentLayerServiceV1.address, true) + + // Mint TLIDs for all users + await talentLayerID.connect(deployer).updateMintFee(0) + await talentLayerID.connect(deployer).updateShortHandlesMaxPrice(0) + await talentLayerID.connect(alice).mint('1', 'alice') + await talentLayerID.connect(bob).mint('1', 'bob') + await talentLayerID.connect(carol).mint('1', 'carol') + await talentLayerID.connect(dave).mint('1', 'dave') + + // Transfers SimpleERC20 tokens to users + await token.connect(deployer).transfer(alice.address, 10000000) + await token.connect(deployer).transfer(bob.address, 10000000) + await token.connect(deployer).transfer(dave.address, 10000000) + }) + + describe('Global contract tests', async function () { + it('Alice owns a PlatformId Id minted by the deployer', async function () { + platformId = (await talentLayerPlatformID.ids(alice.address)).toString() + expect(platformId).to.be.equal('1') + }) + it('All users have TLIDs', async function () { + expect(await talentLayerID.ids(alice.address)).to.be.equal(aliceTlId) + expect(await talentLayerID.ids(bob.address)).to.be.equal(bobTlId) + expect(await talentLayerID.ids(carol.address)).to.be.equal(carolTlId) + expect(await talentLayerID.ids(dave.address)).to.be.equal(daveTlId) + }) + }) + + describe('Service & Proposal creation tests - Before Upgrade', async function () { + it('Users can freely create services without providing tokens', async function () { + const platform = await talentLayerPlatformID.getPlatform(alicePlatformId) + const alicePlatformServicePostingFee = platform.servicePostingFee + // @dev: Signature not activated, will use the same signature for all services + const tx = await talentLayerServiceV1 + .connect(alice) + .createService(aliceTlId, alicePlatformId, cid, fakeSignature, { + value: alicePlatformServicePostingFee, + }) + + const service1Data = await talentLayerServiceV1.services(1) + expect(service1Data.dataUri).to.be.equal(cid) + expect(service1Data.ownerId).to.be.equal(aliceTlId) + expect(service1Data.platformId).to.be.equal(alicePlatformId) + expect(service1Data.acceptedProposalId).to.be.equal(0) + expect(service1Data.transactionId).to.be.equal(0) + expect(service1Data.status).to.be.equal(0) + expect(tx) + .to.emit(talentLayerServiceV1, 'ServiceCreated') + .withArgs(1, aliceTlId, alicePlatformId, cid) + + await talentLayerServiceV1 + .connect(bob) + .createService(bobTlId, alicePlatformId, cid, fakeSignature, { + value: alicePlatformServicePostingFee, + }) + const service2Data = await talentLayerServiceV1.services(2) + + await talentLayerServiceV1 + .connect(carol) + .createService(carolTlId, alicePlatformId, cid, fakeSignature, { + value: alicePlatformServicePostingFee, + }) + const service3Data = await talentLayerServiceV1.services(3) + + await talentLayerServiceV1 + .connect(dave) + .createService(daveTlId, alicePlatformId, cid, fakeSignature, { + value: alicePlatformServicePostingFee, + }) + const service4Data = await talentLayerServiceV1.services(4) + + expect(service2Data.ownerId).to.be.equal(bobTlId) + expect(service3Data.ownerId).to.be.equal(carolTlId) + expect(service4Data.ownerId).to.be.equal(daveTlId) + }) + it('Bob and dave can create 2 MATIC proposals for service 1. ', async function () { + // Service1(alice): 2 proposals created, one validated MATIC, 25% released, 25% reimbursed + // ===> Need to release the rest + 100% reviews + + // Proposal 1 + const tx = await talentLayerServiceV1 + .connect(bob) + .createProposal( + bobTlId, + 1, + ethers.constants.AddressZero, + rateAmount, + alicePlatformId, + cid, + proposalExpirationDate, + fakeSignature, + { + value: alicePlatformProposalPostingFee, + }, + ) + // Proposal 2 + await talentLayerServiceV1 + .connect(dave) + .createProposal( + daveTlId, + 1, + ethers.constants.AddressZero, + rateAmount, + alicePlatformId, + cid, + proposalExpirationDate, + fakeSignature, + { + value: alicePlatformProposalPostingFee, + }, + ) + }) + + it('Alice can validate proposal 1. 25% can be released & 25% reimbursed', async function () { + const totalAmount = getTotalTransactionValue( + talentLayerEscrowV1, + talentLayerPlatformID, + rateAmount, + ) + + // Transaction 1 + await talentLayerEscrowV1.connect(alice).createTransaction(1, bobTlId, metaEvidenceCid, cid, { + value: totalAmount, + }) + + await talentLayerEscrowV1.connect(bob).reimburse(bobTlId, 1, rateAmount / 4) + await talentLayerEscrowV1.connect(alice).release(aliceTlId, 1, rateAmount / 4) + + const transactionData = await talentLayerEscrowV1.connect(alice).getTransactionDetails(1) + expect(transactionData.amount).to.be.equal(rateAmount / 2) + }) + + it('Alice can create 1 ERC20 proposal for service 1. ', async function () { + // Service2(bob): 1 Proposal validated ERC20, 100% released, only buyer review sent + // ===> Need to 100% review + + // Proposal 3 + const tx = await talentLayerServiceV1 + .connect(alice) + .createProposal( + aliceTlId, + 2, + token.address, + rateAmount, + alicePlatformId, + cid, + proposalExpirationDate, + fakeSignature, + { + value: alicePlatformProposalPostingFee, + }, + ) + }) + + it('Bob can validate proposal 2 and release 100%', async function () { + const totalAmount = getTotalTransactionValue( + talentLayerEscrowV1, + talentLayerPlatformID, + rateAmount, + ) + await token.connect(bob).approve(talentLayerEscrowV1.address, totalAmount) + + // Transaction 2 + await talentLayerEscrowV1.connect(bob).createTransaction(2, aliceTlId, metaEvidenceCid, cid) + + await talentLayerEscrowV1.connect(bob).release(bobTlId, 2, rateAmount) + + const transactionData = await talentLayerEscrowV1.connect(alice).getTransactionDetails(2) + expect(transactionData.amount).to.be.equal(0) + }) + + it('Bob can review the transaction', async function () { + await talentLayerReview.connect(bob).mint(bobTlId, 2, cid, 4) + const review = await talentLayerReview.getReview(1) + expect(review.id).to.be.equal(1) + expect(review.ownerId).to.be.equal(aliceTlId) + expect(review.dataUri).to.be.equal(cid) + expect(review.serviceId).to.be.equal(2) + expect(review.rating).to.be.equal(4) + }) + + it('Alice can create 1 ERC20 proposal for service 3. ', async function () { + // Service3(Carol): 2 proposals created ERC20, none validated + // ===> Need to validate one + 100% release + 100% reviews + + // Proposal 4 + await talentLayerServiceV1 + .connect(alice) + .createProposal( + aliceTlId, + 3, + token.address, + rateAmount, + alicePlatformId, + cid, + proposalExpirationDate, + fakeSignature, + { + value: alicePlatformProposalPostingFee, + }, + ) + await talentLayerServiceV1 + .connect(dave) + .createProposal( + daveTlId, + 3, + token.address, + rateAmount, + alicePlatformId, + cid, + proposalExpirationDate, + fakeSignature, + { + value: alicePlatformProposalPostingFee, + }, + ) + }) + // Service4: Nothing + // ===> Need to create proposal after service creation, validate it, release 90%, reimburse 10% and review 100% + }) + + describe.only('Upgrade Service & Escrow contracts', async function () { + it('Upgrade should not alter data', async function () { + const service1DataBeforeUpgrade = await talentLayerServiceV1.services(1) + const proposalDataBeforeUpgrade = await talentLayerServiceV1.getProposal(1, 1) + talentLayerService = await upgradeServiceV1(talentLayerServiceV1.address) + talentLayerEscrow = await upgradeEscrowV1(talentLayerEscrowV1.address) + expect(talentLayerService.address).to.be.equal(talentLayerServiceV1.address) + expect(talentLayerEscrow.address).to.be.equal(talentLayerEscrowV1.address) + const service1DataAfterUpgrade = await talentLayerService.services(1) + const proposalDataAfterUpgrade = await talentLayerService.getProposal(1, 1) + expect(service1DataBeforeUpgrade.ownerId).to.be.equal(service1DataAfterUpgrade.ownerId) + expect(service1DataBeforeUpgrade.dataUri).to.be.equal(service1DataAfterUpgrade.dataUri) + expect(service1DataBeforeUpgrade.platformId).to.be.equal(service1DataAfterUpgrade.platformId) + expect(service1DataBeforeUpgrade.acceptedProposalId).to.be.equal( + service1DataAfterUpgrade.acceptedProposalId, + ) + expect(service1DataAfterUpgrade.rateToken).to.be.equal(ethers.constants.AddressZero) + + expect(proposalDataBeforeUpgrade).to.be.deep.equal(proposalDataAfterUpgrade) + }) + }) +}) + +const getTotalTransactionValue = async ( + talentLayerEscrow: Contract, + talentLayerPlatformID: Contract, + rateAmount: number, +): Promise => { + const protocolEscrowFeeRate = await talentLayerEscrow.protocolEscrowFeeRate() + const originServiceFeeRate = await talentLayerPlatformID.getOriginServiceFeeRate(alicePlatformId) + const originValidatedProposalFeeRate = + await talentLayerPlatformID.getOriginValidatedProposalFeeRate(alicePlatformId) + + return ( + rateAmount + + (rateAmount * (protocolEscrowFeeRate + originValidatedProposalFeeRate + originServiceFeeRate)) / + FEE_DIVIDER + ) +} From 7f9bd582b6a059de9d1883a35e7653c198a9807d Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Tue, 20 Jun 2023 19:37:51 +0200 Subject: [PATCH 84/99] Added tests on services 1 & 2 Signed-off-by: Quentin D.C --- test/batch/upgrades/referral.ts | 65 ++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 13 deletions(-) diff --git a/test/batch/upgrades/referral.ts b/test/batch/upgrades/referral.ts index 7f42c91c..d696a1a9 100644 --- a/test/batch/upgrades/referral.ts +++ b/test/batch/upgrades/referral.ts @@ -10,7 +10,6 @@ import { TalentLayerService, TalentLayerServiceV1, } from '../../../typechain-types' -import { NetworkConfig } from '../../../networkConfig' import { ethers } from 'hardhat' import { deployForV1, upgradeEscrowV1, upgradeServiceV1 } from '../../utils/deploy' import { expect } from 'chai' @@ -39,7 +38,7 @@ const fakeSignature = '0xea53f5cd3f7db698f2fdd38909c58fbd41fe35b54d5b0d6acc3b05555bae1f01795b86ea1d65d8c76954fd6cefd5c59c9c57274966a071be1ee3b783a123ff961b' const alicePlatformProposalPostingFee = 0 -describe('TalentLayer protocol global testing', function () { +describe.only('TalentLayer protocol global testing', function () { let deployer: SignerWithAddress, alice: SignerWithAddress, bob: SignerWithAddress, @@ -56,11 +55,9 @@ describe('TalentLayer protocol global testing', function () { token: SimpleERC20, platformName: string, platformId: string, - mintFee: number, - networkConfig: NetworkConfig, - chainId: number + mintFee: number - const nonListedtoken = '0x6b175474e89094c44da98b954eedeac495271d0f' + const nonListedToken = '0x6b175474e89094c44da98b954eedeac495271d0f' const referralAmount = 20000 before(async function () { @@ -80,7 +77,7 @@ describe('TalentLayer protocol global testing', function () { const mintRole = await talentLayerPlatformID.MINT_ROLE() await talentLayerPlatformID.connect(deployer).grantRole(mintRole, deployer.address) - // we first check the actual minting status (should be ONLY_WHITELIST ) + // we first check the actual minting status (should be ONLY_WHITELIST) const mintingStatus = await talentLayerPlatformID.connect(deployer).mintStatus() expect(mintingStatus).to.be.equal(1) // then we whitelist the deployer and Alice to mint a PlatformId for someone @@ -140,7 +137,7 @@ describe('TalentLayer protocol global testing', function () { it('Users can freely create services without providing tokens', async function () { const platform = await talentLayerPlatformID.getPlatform(alicePlatformId) const alicePlatformServicePostingFee = platform.servicePostingFee - // @dev: Signature not activated, will use the same signature for all services + // @dev: Signature not activated, will use the same signature for all services & proposals const tx = await talentLayerServiceV1 .connect(alice) .createService(aliceTlId, alicePlatformId, cid, fakeSignature, { @@ -185,7 +182,7 @@ describe('TalentLayer protocol global testing', function () { }) it('Bob and dave can create 2 MATIC proposals for service 1. ', async function () { // Service1(alice): 2 proposals created, one validated MATIC, 25% released, 25% reimbursed - // ===> Need to release the rest + 100% reviews + // ===> Need to release the rest + 100% reviews after upgrade // Proposal 1 const tx = await talentLayerServiceV1 @@ -329,16 +326,16 @@ describe('TalentLayer protocol global testing', function () { // ===> Need to create proposal after service creation, validate it, release 90%, reimburse 10% and review 100% }) - describe.only('Upgrade Service & Escrow contracts', async function () { + describe('Upgrade Service & Escrow contracts', async function () { it('Upgrade should not alter data', async function () { const service1DataBeforeUpgrade = await talentLayerServiceV1.services(1) - const proposalDataBeforeUpgrade = await talentLayerServiceV1.getProposal(1, 1) + const proposalDataBeforeUpgrade = await talentLayerServiceV1.getProposal(1, 2) talentLayerService = await upgradeServiceV1(talentLayerServiceV1.address) talentLayerEscrow = await upgradeEscrowV1(talentLayerEscrowV1.address) expect(talentLayerService.address).to.be.equal(talentLayerServiceV1.address) expect(talentLayerEscrow.address).to.be.equal(talentLayerEscrowV1.address) const service1DataAfterUpgrade = await talentLayerService.services(1) - const proposalDataAfterUpgrade = await talentLayerService.getProposal(1, 1) + const proposalDataAfterUpgrade = await talentLayerService.getProposal(1, 2) expect(service1DataBeforeUpgrade.ownerId).to.be.equal(service1DataAfterUpgrade.ownerId) expect(service1DataBeforeUpgrade.dataUri).to.be.equal(service1DataAfterUpgrade.dataUri) expect(service1DataBeforeUpgrade.platformId).to.be.equal(service1DataAfterUpgrade.platformId) @@ -347,7 +344,49 @@ describe('TalentLayer protocol global testing', function () { ) expect(service1DataAfterUpgrade.rateToken).to.be.equal(ethers.constants.AddressZero) - expect(proposalDataBeforeUpgrade).to.be.deep.equal(proposalDataAfterUpgrade) + expect(proposalDataBeforeUpgrade.ownerId).to.be.equal(proposalDataAfterUpgrade.ownerId) + expect(proposalDataBeforeUpgrade.dataUri).to.be.equal(proposalDataAfterUpgrade.dataUri) + expect(proposalDataBeforeUpgrade.rateAmount).to.be.equal(proposalDataAfterUpgrade.rateAmount) + expect(proposalDataBeforeUpgrade.platformId).to.be.equal(proposalDataAfterUpgrade.platformId) + expect(proposalDataBeforeUpgrade.expirationDate).to.be.equal( + proposalDataAfterUpgrade.expirationDate, + ) + expect(proposalDataBeforeUpgrade.rateToken).to.be.equal(ethers.constants.AddressZero) + }) + describe('For Service1 => Check whether escrow balance can be released & reimbursed after an upgrade', async function () { + it('Alice can release 40% of the remaining escrow amount & Bob can reimburse 10% of the remaining escrow amount', async function () { + await talentLayerEscrow.connect(alice).release(aliceTlId, 1, (rateAmount * 4) / 10) + await talentLayerEscrow.connect(bob).reimburse(bobTlId, 1, rateAmount / 10) + const transactionData = await talentLayerEscrow.connect(alice).getTransactionDetails(1) + expect(transactionData.amount).to.be.equal(0) + }) + it('Bob & Alice can both review the service', async function () { + await talentLayerReview.connect(bob).mint(bobTlId, 1, cid, 5) + const bobReview = await talentLayerReview.getReview(2) + expect(bobReview.id).to.be.equal(2) + expect(bobReview.ownerId).to.be.equal(aliceTlId) + expect(bobReview.dataUri).to.be.equal(cid) + expect(bobReview.serviceId).to.be.equal(1) + expect(bobReview.rating).to.be.equal(5) + await talentLayerReview.connect(alice).mint(aliceTlId, 1, cid, 5) + const aliceReview = await talentLayerReview.getReview(3) + expect(aliceReview.id).to.be.equal(3) + expect(aliceReview.ownerId).to.be.equal(bobTlId) + expect(aliceReview.dataUri).to.be.equal(cid) + expect(aliceReview.serviceId).to.be.equal(1) + expect(aliceReview.rating).to.be.equal(5) + }) + }) + describe('For Service2 => Check whether a service can be reviewed after an upgrade', async function () { + it('Alice can review the service', async function () { + await talentLayerReview.connect(alice).mint(aliceTlId, 2, cid, 5) + const aliceReview = await talentLayerReview.getReview(4) + expect(aliceReview.id).to.be.equal(4) + expect(aliceReview.ownerId).to.be.equal(bobTlId) + expect(aliceReview.dataUri).to.be.equal(cid) + expect(aliceReview.serviceId).to.be.equal(2) + expect(aliceReview.rating).to.be.equal(5) + }) }) }) }) From 31010fc16663ca9a69500e99bfe4651b28a5200f Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Tue, 20 Jun 2023 19:50:41 +0200 Subject: [PATCH 85/99] Added tests on services 3 Signed-off-by: Quentin D.C --- .deployment/mumbai.json | 13 +- .openzeppelin/polygon-mumbai.json | 3279 ++++++++++++++++++++++------- test/batch/upgrades/referral.ts | 31 +- 3 files changed, 2520 insertions(+), 803 deletions(-) diff --git a/.deployment/mumbai.json b/.deployment/mumbai.json index ec6951d5..729b8a46 100644 --- a/.deployment/mumbai.json +++ b/.deployment/mumbai.json @@ -1,8 +1,9 @@ { - "talentLayerPlatformIdAddress": "0xEFD8dbC421380Ee04BAdB69216a0FD97F64CbFD4", - "talentLayerIdAddress": "0x3F87289e6Ec2D05C32d8A74CCfb30773fF549306", - "talentLayerServiceAddress": "0x27ED516dC1df64b4c1517A64aa2Bb72a434a5A6D", - "talentLayerReviewAddress": "0x050F59E1871d3B7ca97e6fb9DCE64b3818b14B18", - "talentLayerArbitratorAddress": "0x2CA01a0058cfB3cc4755a7773881ea88eCfBba7C", - "talentLayerEscrowAddress": "0x4bE920eC3e8552292B2147480111063E0dc36872" + "talentLayerPlatformIdAddress": "0xE95a9d7d673716e40B8aa9851592672D6D697c25", + "talentLayerIdAddress": "0x87a247A1Aed184F7BC2b4F287Fc23D82E720721b", + "talentLayerServiceAddress": "0x9B7C6FB51D2EEE39b259BDe874710642120a58ED", + "talentLayerReviewAddress": "0x815035199D281be97D092710fE659445F1EB0DC9", + "talentLayerArbitratorAddress": "0x3fBE0B906feF4507caB4e3E17DeDaBcA5b43bda1", + "talentLayerEscrowAddress": "0xC184101F1C1E4D71bd18F88FB7f36F53ec4F2De8", + "simpleERC20Address": "0x1A87740Fc249E8F917AF7D1F99bfBD4eEd6f98A1" } \ No newline at end of file diff --git a/.openzeppelin/polygon-mumbai.json b/.openzeppelin/polygon-mumbai.json index 96dd0d0f..8482d372 100644 --- a/.openzeppelin/polygon-mumbai.json +++ b/.openzeppelin/polygon-mumbai.json @@ -25,6 +25,81 @@ "address": "0x4bE920eC3e8552292B2147480111063E0dc36872", "txHash": "0xb2eccc32f9e60d7bbb7b0297ff37ae643a2c0bab4946c86f5ceccbda77e7d03e", "kind": "uups" + }, + { + "address": "0xe7cF60676481E7EDf4a65d873fdF1df5f35041d8", + "txHash": "0x72a093efefb6520d38bcc5b3a60c9aff0b31781f50223709082f8b2f70f9aac3", + "kind": "uups" + }, + { + "address": "0x4a1d2953Eb422C9D57c05e494D1c646359281086", + "txHash": "0xa4e22d4e49c6b80519d4eb0ac7f7994dd10cdd1c8ec30374e08c8a4efe40b171", + "kind": "uups" + }, + { + "address": "0x324b099eE546aAb9CbfA364e8473964808Ec9791", + "txHash": "0xebdaaef4b9ade450259c96e3fc98bddcbe7eb08e758edaf062cf01e0b1bdf308", + "kind": "uups" + }, + { + "address": "0x57d97B065e55Be23B69bb5Ef12AA10F03E60e666", + "txHash": "0x7fca3ea858f59b5e391f69d27d83479db2bff1f6cd09dd8f3a9ef56e97355c3a", + "kind": "uups" + }, + { + "address": "0x86D6E6e059188744f327c56d615e441c207EDAcc", + "txHash": "0xb88702f76f56e13c715f577449255e654ab173bf5f61a31aa860ebf8ed0652f6", + "kind": "uups" + }, + { + "address": "0xA4f18F9Ead22c7806312a2C5Bb13180862CbB2a4", + "txHash": "0x8d02fc775f0c76fba9fd62f44b9a66315cf8a77e8d3c045310493e4455d87696", + "kind": "uups" + }, + { + "address": "0xBd6561a6AfBC0d37F686fab22FfC07618d29b895", + "txHash": "0x9dd9fd0896cc8c949b44a0dec9de557ef5ce46606667ced12cae4ae584339cf6", + "kind": "uups" + }, + { + "address": "0x839C7b9F4c006499bcD2Ab3585F94CAC25dE47C6", + "txHash": "0x05e505c29768d3a44ee07845a9b83f0b4c86208d0b1998da1e8e451824ba2ae3", + "kind": "uups" + }, + { + "address": "0x999803a07C2769a585bDAf03Cb967F5927FB388E", + "txHash": "0xb41356e140e4e16646da63827ccb017bc82040d7cc7962bb20afcffc96781511", + "kind": "uups" + }, + { + "address": "0x684456006ec704A82f6fB5a39F671E82271aa1e9", + "txHash": "0xba3eb8a4186c673a22faa180a23d1239d2692a2a4528d5f37c070bb4336c7056", + "kind": "uups" + }, + { + "address": "0xE95a9d7d673716e40B8aa9851592672D6D697c25", + "txHash": "0xfc60f72212ed9b2e91a76fda0970e21e4a2497c4c295c00b1f562b3258de6981", + "kind": "uups" + }, + { + "address": "0x87a247A1Aed184F7BC2b4F287Fc23D82E720721b", + "txHash": "0x7c1cdf22df899c7184d4e97378145c50c4ac925a55ab78a7a35479c00d77850f", + "kind": "uups" + }, + { + "address": "0x9B7C6FB51D2EEE39b259BDe874710642120a58ED", + "txHash": "0x56386681e00f646cd517fff0136fcf78b81f4aaff5e0d86e6fd4e83240c51cd2", + "kind": "uups" + }, + { + "address": "0x815035199D281be97D092710fE659445F1EB0DC9", + "txHash": "0xa0e9da97d0b4584193a8240ea530a189b43c681ebe8e80211560a23aee6a9dac", + "kind": "uups" + }, + { + "address": "0xC184101F1C1E4D71bd18F88FB7f36F53ec4F2De8", + "txHash": "0xe24c084fbbfedb3347ce3c4e2ed0901e2e7929861d980634d7ef55263eab3e74", + "kind": "uups" } ], "impls": { @@ -794,9 +869,9 @@ } } }, - "c980df0f3f2d12ed5c153d563a1fbbb3da4380540f0f81a91a88015668a2090b": { - "address": "0xB60f8b4f06B66ecc75806cC5bbfc17b6eF8e56D7", - "txHash": "0xbe5bd8de2d13887a8f6109045d69507b8ab9e16cb1875656b2ca746af012603f", + "452eb25e1c135f95b329252e20212c01eb69015592373af7097bb11bb44a9ae1": { + "address": "0xb943224A83e4C3340e8b974dBE559692D9BE3e40", + "txHash": "0x7a412a32f2f50ec0f91d6e0198d78df1272da5cb1c49f0d9944b6c7d673972fe", "layout": { "solcVersion": "0.8.17", "storage": [ @@ -806,7 +881,7 @@ "slot": "0", "type": "t_uint8", "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:62", "retypedFrom": "bool" }, { @@ -815,7 +890,7 @@ "slot": "0", "type": "t_bool", "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:67" }, { "label": "__gap", @@ -823,143 +898,183 @@ "slot": "1", "type": "t_array(t_uint256)50_storage", "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + "src": "@openzeppelin\\contracts-upgradeable\\utils\\ContextUpgradeable.sol:36" }, { - "label": "_owner", + "label": "__gap", "offset": 0, "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + "type": "t_array(t_uint256)50_storage", + "contract": "ERC165Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\utils\\introspection\\ERC165Upgradeable.sol:41" }, { - "label": "__gap", + "label": "_name", "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + "slot": "101", + "type": "t_string_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:25" }, { - "label": "_trustedForwarders", + "label": "_symbol", "offset": 0, - "slot": "101", - "type": "t_mapping(t_address,t_bool)", - "contract": "ERC2771RecipientUpgradeable", - "src": "contracts/libs/ERC2771RecipientUpgradeable.sol:29" + "slot": "102", + "type": "t_string_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:28" }, { - "label": "__gap", + "label": "_owners", "offset": 0, - "slot": "102", - "type": "t_array(t_uint256)50_storage", - "contract": "ERC1967UpgradeUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:211" + "slot": "103", + "type": "t_mapping(t_uint256,t_address)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:31" }, { - "label": "__gap", + "label": "_balances", "offset": 0, - "slot": "152", - "type": "t_array(t_uint256)50_storage", - "contract": "UUPSUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:107" + "slot": "104", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:34" + }, + { + "label": "_tokenApprovals", + "offset": 0, + "slot": "105", + "type": "t_mapping(t_uint256,t_address)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:37" + }, + { + "label": "_operatorApprovals", + "offset": 0, + "slot": "106", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:40" }, { "label": "__gap", "offset": 0, - "slot": "202", - "type": "t_array(t_uint256)50_storage", - "contract": "ERC165Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + "slot": "107", + "type": "t_array(t_uint256)44_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:514" }, { "label": "_roles", "offset": 0, - "slot": "252", + "slot": "151", "type": "t_mapping(t_bytes32,t_struct(RoleData)58_storage)", "contract": "AccessControlUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61" + "src": "@openzeppelin\\contracts-upgradeable\\access\\AccessControlUpgradeable.sol:61" }, { "label": "__gap", "offset": 0, - "slot": "253", + "slot": "152", "type": "t_array(t_uint256)49_storage", "contract": "AccessControlUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:259" + "src": "@openzeppelin\\contracts-upgradeable\\access\\AccessControlUpgradeable.sol:259" }, { - "label": "nextServiceId", + "label": "__gap", + "offset": 0, + "slot": "201", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\ERC1967\\ERC1967UpgradeUpgradeable.sol:211" + }, + { + "label": "__gap", + "offset": 0, + "slot": "251", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\UUPSUpgradeable.sol:107" + }, + { + "label": "takenNames", + "offset": 0, + "slot": "301", + "type": "t_mapping(t_string_memory_ptr,t_bool)", + "contract": "TalentLayerPlatformID", + "src": "contracts\\TalentLayerPlatformID.sol:65" + }, + { + "label": "platforms", "offset": 0, "slot": "302", - "type": "t_uint256", - "contract": "TalentLayerService", - "src": "contracts/TalentLayerService.sol:171" + "type": "t_mapping(t_uint256,t_struct(Platform)12888_storage)", + "contract": "TalentLayerPlatformID", + "src": "contracts\\TalentLayerPlatformID.sol:70" }, { - "label": "tlId", + "label": "validArbitrators", "offset": 0, "slot": "303", - "type": "t_contract(ITalentLayerID)15000", - "contract": "TalentLayerService", - "src": "contracts/TalentLayerService.sol:176" + "type": "t_mapping(t_address,t_bool)", + "contract": "TalentLayerPlatformID", + "src": "contracts\\TalentLayerPlatformID.sol:75" }, { - "label": "talentLayerPlatformIdContract", + "label": "whitelist", "offset": 0, "slot": "304", - "type": "t_contract(ITalentLayerPlatformID)15212", - "contract": "TalentLayerService", - "src": "contracts/TalentLayerService.sol:181" + "type": "t_mapping(t_address,t_bool)", + "contract": "TalentLayerPlatformID", + "src": "contracts\\TalentLayerPlatformID.sol:80" }, { - "label": "services", + "label": "internalArbitrators", "offset": 0, "slot": "305", - "type": "t_mapping(t_uint256,t_struct(Service)13472_storage)", - "contract": "TalentLayerService", - "src": "contracts/TalentLayerService.sol:186" + "type": "t_mapping(t_address,t_bool)", + "contract": "TalentLayerPlatformID", + "src": "contracts\\TalentLayerPlatformID.sol:86" }, { - "label": "proposals", + "label": "ids", "offset": 0, "slot": "306", - "type": "t_mapping(t_uint256,t_mapping(t_uint256,t_struct(Proposal)13488_storage))", - "contract": "TalentLayerService", - "src": "contracts/TalentLayerService.sol:191" + "type": "t_mapping(t_address,t_uint256)", + "contract": "TalentLayerPlatformID", + "src": "contracts\\TalentLayerPlatformID.sol:91" }, { - "label": "serviceNonce", + "label": "mintFee", "offset": 0, "slot": "307", - "type": "t_mapping(t_uint256,t_uint256)", - "contract": "TalentLayerService", - "src": "contracts/TalentLayerService.sol:196" + "type": "t_uint256", + "contract": "TalentLayerPlatformID", + "src": "contracts\\TalentLayerPlatformID.sol:96" }, { - "label": "proposalNonce", + "label": "minArbitrationFeeTimeout", "offset": 0, "slot": "308", - "type": "t_mapping(t_uint256,t_uint256)", - "contract": "TalentLayerService", - "src": "contracts/TalentLayerService.sol:201" + "type": "t_uint256", + "contract": "TalentLayerPlatformID", + "src": "contracts\\TalentLayerPlatformID.sol:106" }, { - "label": "allowedTokenList", + "label": "nextPlatformId", "offset": 0, "slot": "309", - "type": "t_mapping(t_address,t_struct(AllowedToken)13493_storage)", - "contract": "TalentLayerService", - "src": "contracts/TalentLayerService.sol:206" + "type": "t_struct(Counter)3290_storage", + "contract": "TalentLayerPlatformID", + "src": "contracts\\TalentLayerPlatformID.sol:111" }, { - "label": "minCompletionPercentage", + "label": "mintStatus", "offset": 0, "slot": "310", - "type": "t_uint256", - "contract": "TalentLayerService", - "src": "contracts/TalentLayerService.sol:211" + "type": "t_enum(MintStatus)12864", + "contract": "TalentLayerPlatformID", + "src": "contracts\\TalentLayerPlatformID.sol:116" } ], "types": { @@ -967,6 +1082,10 @@ "label": "address", "numberOfBytes": "20" }, + "t_array(t_uint256)44_storage": { + "label": "uint256[44]", + "numberOfBytes": "1408" + }, "t_array(t_uint256)49_storage": { "label": "uint256[49]", "numberOfBytes": "1568" @@ -983,30 +1102,20 @@ "label": "bytes32", "numberOfBytes": "32" }, - "t_contract(ITalentLayerID)15000": { - "label": "contract ITalentLayerID", - "numberOfBytes": "20" + "t_bytes_storage": { + "label": "bytes", + "numberOfBytes": "32" }, - "t_contract(ITalentLayerPlatformID)15212": { - "label": "contract ITalentLayerPlatformID", + "t_contract(Arbitrator)7789": { + "label": "contract Arbitrator", "numberOfBytes": "20" }, - "t_enum(ProposalStatus)13458": { - "label": "enum TalentLayerService.ProposalStatus", - "members": [ - "Pending", - "Validated" - ], - "numberOfBytes": "1" - }, - "t_enum(Status)13455": { - "label": "enum TalentLayerService.Status", + "t_enum(MintStatus)12864": { + "label": "enum TalentLayerPlatformID.MintStatus", "members": [ - "Opened", - "Confirmed", - "Finished", - "Cancelled", - "Uncompleted" + "ON_PAUSE", + "ONLY_WHITELIST", + "PUBLIC" ], "numberOfBytes": "1" }, @@ -1014,99 +1123,121 @@ "label": "mapping(address => bool)", "numberOfBytes": "32" }, - "t_mapping(t_address,t_struct(AllowedToken)13493_storage)": { - "label": "mapping(address => struct TalentLayerService.AllowedToken)", + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", "numberOfBytes": "32" }, "t_mapping(t_bytes32,t_struct(RoleData)58_storage)": { "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", "numberOfBytes": "32" }, - "t_mapping(t_uint256,t_mapping(t_uint256,t_struct(Proposal)13488_storage))": { - "label": "mapping(uint256 => mapping(uint256 => struct TalentLayerService.Proposal))", + "t_mapping(t_string_memory_ptr,t_bool)": { + "label": "mapping(string => bool)", "numberOfBytes": "32" }, - "t_mapping(t_uint256,t_struct(Proposal)13488_storage)": { - "label": "mapping(uint256 => struct TalentLayerService.Proposal)", + "t_mapping(t_uint256,t_address)": { + "label": "mapping(uint256 => address)", "numberOfBytes": "32" }, - "t_mapping(t_uint256,t_struct(Service)13472_storage)": { - "label": "mapping(uint256 => struct TalentLayerService.Service)", + "t_mapping(t_uint256,t_struct(Platform)12888_storage)": { + "label": "mapping(uint256 => struct TalentLayerPlatformID.Platform)", "numberOfBytes": "32" }, - "t_mapping(t_uint256,t_uint256)": { - "label": "mapping(uint256 => uint256)", + "t_string_memory_ptr": { + "label": "string", "numberOfBytes": "32" }, "t_string_storage": { "label": "string", "numberOfBytes": "32" }, - "t_struct(AllowedToken)13493_storage": { - "label": "struct TalentLayerService.AllowedToken", + "t_struct(Counter)3290_storage": { + "label": "struct CountersUpgradeable.Counter", "members": [ { - "label": "isWhitelisted", - "type": "t_bool", - "offset": 0, - "slot": "0" - }, - { - "label": "minimumTransactionAmount", + "label": "_value", "type": "t_uint256", "offset": 0, - "slot": "1" + "slot": "0" } ], - "numberOfBytes": "64" + "numberOfBytes": "32" }, - "t_struct(Proposal)13488_storage": { - "label": "struct TalentLayerService.Proposal", + "t_struct(Platform)12888_storage": { + "label": "struct TalentLayerPlatformID.Platform", "members": [ { - "label": "status", - "type": "t_enum(ProposalStatus)13458", + "label": "id", + "type": "t_uint256", "offset": 0, "slot": "0" }, { - "label": "ownerId", - "type": "t_uint256", + "label": "name", + "type": "t_string_storage", "offset": 0, "slot": "1" }, { - "label": "rateToken", - "type": "t_address", + "label": "dataUri", + "type": "t_string_storage", "offset": 0, "slot": "2" }, { - "label": "rateAmount", - "type": "t_uint256", + "label": "originServiceFeeRate", + "type": "t_uint16", "offset": 0, "slot": "3" }, { - "label": "platformId", + "label": "originValidatedProposalFeeRate", + "type": "t_uint16", + "offset": 2, + "slot": "3" + }, + { + "label": "servicePostingFee", "type": "t_uint256", "offset": 0, "slot": "4" }, { - "label": "dataUri", - "type": "t_string_storage", + "label": "proposalPostingFee", + "type": "t_uint256", "offset": 0, "slot": "5" }, { - "label": "expirationDate", - "type": "t_uint256", + "label": "arbitrator", + "type": "t_contract(Arbitrator)7789", "offset": 0, "slot": "6" + }, + { + "label": "arbitratorExtraData", + "type": "t_bytes_storage", + "offset": 0, + "slot": "7" + }, + { + "label": "arbitrationFeeTimeout", + "type": "t_uint256", + "offset": 0, + "slot": "8" + }, + { + "label": "signer", + "type": "t_address", + "offset": 0, + "slot": "9" } ], - "numberOfBytes": "224" + "numberOfBytes": "320" }, "t_struct(RoleData)58_storage": { "label": "struct AccessControlUpgradeable.RoleData", @@ -1126,47 +1257,9 @@ ], "numberOfBytes": "64" }, - "t_struct(Service)13472_storage": { - "label": "struct TalentLayerService.Service", - "members": [ - { - "label": "status", - "type": "t_enum(Status)13455", - "offset": 0, - "slot": "0" - }, - { - "label": "ownerId", - "type": "t_uint256", - "offset": 0, - "slot": "1" - }, - { - "label": "acceptedProposalId", - "type": "t_uint256", - "offset": 0, - "slot": "2" - }, - { - "label": "dataUri", - "type": "t_string_storage", - "offset": 0, - "slot": "3" - }, - { - "label": "transactionId", - "type": "t_uint256", - "offset": 0, - "slot": "4" - }, - { - "label": "platformId", - "type": "t_uint256", - "offset": 0, - "slot": "5" - } - ], - "numberOfBytes": "192" + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" }, "t_uint256": { "label": "uint256", @@ -1179,9 +1272,9 @@ } } }, - "88ab1cdc37255e380eb6a7ab9e7ed0ef4fb8be10681fc961f9547c5db21335ec": { - "address": "0x3d18c9C94faD1444F9c2bD052D5c7D6D2C52e420", - "txHash": "0x5207e2000f745e2a4d10d4d2d327c24bdb04bf359fea1b8302348698537dc8a6", + "f9e7916a1c316964ab24794f96ac3ee47b57790f1fb37e7a459ebb7c82af0d2e": { + "address": "0x35BA74f9D1de2E1401798ae5c71678FEd4b25380", + "txHash": "0x8f6e51fe0b9b012092985b3ed726fb4e6581b62f52762fc9208a35ca3f3d26a8", "layout": { "solcVersion": "0.8.17", "storage": [ @@ -1191,7 +1284,7 @@ "slot": "0", "type": "t_uint8", "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:62", "retypedFrom": "bool" }, { @@ -1200,7 +1293,7 @@ "slot": "0", "type": "t_bool", "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:67" }, { "label": "__gap", @@ -1208,7 +1301,7 @@ "slot": "1", "type": "t_array(t_uint256)50_storage", "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + "src": "@openzeppelin\\contracts-upgradeable\\utils\\ContextUpgradeable.sol:36" }, { "label": "_owner", @@ -1216,7 +1309,7 @@ "slot": "51", "type": "t_address", "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:22" }, { "label": "__gap", @@ -1224,7 +1317,7 @@ "slot": "52", "type": "t_array(t_uint256)49_storage", "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:94" }, { "label": "_trustedForwarders", @@ -1232,7 +1325,7 @@ "slot": "101", "type": "t_mapping(t_address,t_bool)", "contract": "ERC2771RecipientUpgradeable", - "src": "contracts/libs/ERC2771RecipientUpgradeable.sol:29" + "src": "contracts\\libs\\ERC2771RecipientUpgradeable.sol:29" }, { "label": "__gap", @@ -1240,7 +1333,7 @@ "slot": "102", "type": "t_array(t_uint256)50_storage", "contract": "ERC165Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + "src": "@openzeppelin\\contracts-upgradeable\\utils\\introspection\\ERC165Upgradeable.sol:41" }, { "label": "_name", @@ -1248,7 +1341,7 @@ "slot": "152", "type": "t_string_storage", "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:25" + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:25" }, { "label": "_symbol", @@ -1256,7 +1349,7 @@ "slot": "153", "type": "t_string_storage", "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:28" + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:28" }, { "label": "_owners", @@ -1264,7 +1357,7 @@ "slot": "154", "type": "t_mapping(t_uint256,t_address)", "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:31" + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:31" }, { "label": "_balances", @@ -1272,7 +1365,7 @@ "slot": "155", "type": "t_mapping(t_address,t_uint256)", "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:34" + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:34" }, { "label": "_tokenApprovals", @@ -1280,7 +1373,7 @@ "slot": "156", "type": "t_mapping(t_uint256,t_address)", "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:37" + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:37" }, { "label": "_operatorApprovals", @@ -1288,7 +1381,7 @@ "slot": "157", "type": "t_mapping(t_address,t_mapping(t_address,t_bool))", "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:40" + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:40" }, { "label": "__gap", @@ -1296,7 +1389,7 @@ "slot": "158", "type": "t_array(t_uint256)44_storage", "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:514" + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:514" }, { "label": "__gap", @@ -1304,7 +1397,7 @@ "slot": "202", "type": "t_array(t_uint256)50_storage", "contract": "ERC1967UpgradeUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:211" + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\ERC1967\\ERC1967UpgradeUpgradeable.sol:211" }, { "label": "__gap", @@ -1312,55 +1405,103 @@ "slot": "252", "type": "t_array(t_uint256)50_storage", "contract": "UUPSUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:107" + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\UUPSUpgradeable.sol:107" }, { - "label": "nextReviewId", + "label": "talentLayerPlatformIdContract", "offset": 0, "slot": "302", - "type": "t_struct(Counter)3290_storage", - "contract": "TalentLayerReview", - "src": "contracts/TalentLayerReview.sol:47" + "type": "t_contract(ITalentLayerPlatformID)16292", + "contract": "TalentLayerID", + "src": "contracts\\TalentLayerID.sol:70" }, { - "label": "reviews", + "label": "takenHandles", "offset": 0, "slot": "303", - "type": "t_mapping(t_uint256,t_struct(Review)12991_storage)", - "contract": "TalentLayerReview", - "src": "contracts/TalentLayerReview.sol:52" + "type": "t_mapping(t_string_memory_ptr,t_bool)", + "contract": "TalentLayerID", + "src": "contracts\\TalentLayerID.sol:75" }, { - "label": "hasBuyerBeenReviewed", + "label": "profiles", "offset": 0, "slot": "304", - "type": "t_mapping(t_uint256,t_bool)", - "contract": "TalentLayerReview", - "src": "contracts/TalentLayerReview.sol:57" + "type": "t_mapping(t_uint256,t_struct(Profile)11510_storage)", + "contract": "TalentLayerID", + "src": "contracts\\TalentLayerID.sol:80" }, { - "label": "hasSellerBeenReviewed", + "label": "ids", "offset": 0, "slot": "305", - "type": "t_mapping(t_uint256,t_bool)", - "contract": "TalentLayerReview", - "src": "contracts/TalentLayerReview.sol:62" + "type": "t_mapping(t_address,t_uint256)", + "contract": "TalentLayerID", + "src": "contracts\\TalentLayerID.sol:85" }, { - "label": "tlId", + "label": "mintFee", "offset": 0, "slot": "306", - "type": "t_contract(ITalentLayerID)15000", - "contract": "TalentLayerReview", - "src": "contracts/TalentLayerReview.sol:67" + "type": "t_uint256", + "contract": "TalentLayerID", + "src": "contracts\\TalentLayerID.sol:90" }, { - "label": "talentLayerService", + "label": "nextProfileId", "offset": 0, "slot": "307", - "type": "t_contract(ITalentLayerService)15385", - "contract": "TalentLayerReview", - "src": "contracts/TalentLayerReview.sol:72" + "type": "t_struct(Counter)3290_storage", + "contract": "TalentLayerID", + "src": "contracts\\TalentLayerID.sol:95" + }, + { + "label": "delegates", + "offset": 0, + "slot": "308", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_bool))", + "contract": "TalentLayerID", + "src": "contracts\\TalentLayerID.sol:100" + }, + { + "label": "whitelistMerkleRoot", + "offset": 0, + "slot": "309", + "type": "t_bytes32", + "contract": "TalentLayerID", + "src": "contracts\\TalentLayerID.sol:105" + }, + { + "label": "mintStatus", + "offset": 0, + "slot": "310", + "type": "t_enum(MintStatus)11501", + "contract": "TalentLayerID", + "src": "contracts\\TalentLayerID.sol:110" + }, + { + "label": "shortHandlesMaxPrice", + "offset": 0, + "slot": "311", + "type": "t_uint256", + "contract": "TalentLayerID", + "src": "contracts\\TalentLayerID.sol:115" + }, + { + "label": "hasActivity", + "offset": 0, + "slot": "312", + "type": "t_mapping(t_uint256,t_bool)", + "contract": "TalentLayerID", + "src": "contracts\\TalentLayerID.sol:120" + }, + { + "label": "isServiceContract", + "offset": 0, + "slot": "313", + "type": "t_mapping(t_address,t_bool)", + "contract": "TalentLayerID", + "src": "contracts\\TalentLayerID.sol:125" } ], "types": { @@ -1384,14 +1525,23 @@ "label": "bool", "numberOfBytes": "1" }, - "t_contract(ITalentLayerID)15000": { - "label": "contract ITalentLayerID", - "numberOfBytes": "20" + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" }, - "t_contract(ITalentLayerService)15385": { - "label": "contract ITalentLayerService", + "t_contract(ITalentLayerPlatformID)16292": { + "label": "contract ITalentLayerPlatformID", "numberOfBytes": "20" }, + "t_enum(MintStatus)11501": { + "label": "enum TalentLayerID.MintStatus", + "members": [ + "ON_PAUSE", + "ONLY_WHITELIST", + "PUBLIC" + ], + "numberOfBytes": "1" + }, "t_mapping(t_address,t_bool)": { "label": "mapping(address => bool)", "numberOfBytes": "32" @@ -1404,6 +1554,10 @@ "label": "mapping(address => uint256)", "numberOfBytes": "32" }, + "t_mapping(t_string_memory_ptr,t_bool)": { + "label": "mapping(string => bool)", + "numberOfBytes": "32" + }, "t_mapping(t_uint256,t_address)": { "label": "mapping(uint256 => address)", "numberOfBytes": "32" @@ -1412,8 +1566,16 @@ "label": "mapping(uint256 => bool)", "numberOfBytes": "32" }, - "t_mapping(t_uint256,t_struct(Review)12991_storage)": { - "label": "mapping(uint256 => struct TalentLayerReview.Review)", + "t_mapping(t_uint256,t_mapping(t_address,t_bool))": { + "label": "mapping(uint256 => mapping(address => bool))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Profile)11510_storage)": { + "label": "mapping(uint256 => struct TalentLayerID.Profile)", + "numberOfBytes": "32" + }, + "t_string_memory_ptr": { + "label": "string", "numberOfBytes": "32" }, "t_string_storage": { @@ -1432,8 +1594,8 @@ ], "numberOfBytes": "32" }, - "t_struct(Review)12991_storage": { - "label": "struct TalentLayerReview.Review", + "t_struct(Profile)11510_storage": { + "label": "struct TalentLayerID.Profile", "members": [ { "label": "id", @@ -1442,31 +1604,25 @@ "slot": "0" }, { - "label": "ownerId", - "type": "t_uint256", + "label": "handle", + "type": "t_string_storage", "offset": 0, "slot": "1" }, { - "label": "dataUri", - "type": "t_string_storage", + "label": "platformId", + "type": "t_uint256", "offset": 0, "slot": "2" }, { - "label": "serviceId", - "type": "t_uint256", + "label": "dataUri", + "type": "t_string_storage", "offset": 0, "slot": "3" - }, - { - "label": "rating", - "type": "t_uint256", - "offset": 0, - "slot": "4" } ], - "numberOfBytes": "160" + "numberOfBytes": "128" }, "t_uint256": { "label": "uint256", @@ -1479,9 +1635,9 @@ } } }, - "09aac2d047d78f74214c535af98f3c37c37ef8536acce8b970ff6e54e333c9c1": { - "address": "0x7d5e41423179901E507D168967A4edE0dD088c8a", - "txHash": "0x25f75b2b14e9166f6b1798f5b06770be1637ff56249acd65bc71d57711e944df", + "c980df0f3f2d12ed5c153d563a1fbbb3da4380540f0f81a91a88015668a2090b": { + "address": "0xA685EEBC106CC8FAcaFca58236F2ece3Ee9f1a29", + "txHash": "0x41074e203dff9f4a7b89523db272d10f09efeed401ac741a85beb6a257070ad7", "layout": { "solcVersion": "0.8.17", "storage": [ @@ -1491,7 +1647,7 @@ "slot": "0", "type": "t_uint8", "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:62", "retypedFrom": "bool" }, { @@ -1500,7 +1656,7 @@ "slot": "0", "type": "t_bool", "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:67" }, { "label": "__gap", @@ -1508,7 +1664,7 @@ "slot": "1", "type": "t_array(t_uint256)50_storage", "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + "src": "@openzeppelin\\contracts-upgradeable\\utils\\ContextUpgradeable.sol:36" }, { "label": "_owner", @@ -1516,7 +1672,7 @@ "slot": "51", "type": "t_address", "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:22" }, { "label": "__gap", @@ -1524,7 +1680,7 @@ "slot": "52", "type": "t_array(t_uint256)49_storage", "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:94" }, { "label": "_trustedForwarders", @@ -1532,111 +1688,119 @@ "slot": "101", "type": "t_mapping(t_address,t_bool)", "contract": "ERC2771RecipientUpgradeable", - "src": "contracts/libs/ERC2771RecipientUpgradeable.sol:29" + "src": "contracts\\libs\\ERC2771RecipientUpgradeable.sol:29" }, { - "label": "_paused", + "label": "__gap", "offset": 0, "slot": "102", - "type": "t_bool", - "contract": "PausableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:29" + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\ERC1967\\ERC1967UpgradeUpgradeable.sol:211" }, { "label": "__gap", "offset": 0, - "slot": "103", - "type": "t_array(t_uint256)49_storage", - "contract": "PausableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:116" + "slot": "152", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\UUPSUpgradeable.sol:107" }, { "label": "__gap", "offset": 0, - "slot": "152", + "slot": "202", "type": "t_array(t_uint256)50_storage", - "contract": "ERC1967UpgradeUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:211" - }, - { - "label": "__gap", - "offset": 0, - "slot": "202", - "type": "t_array(t_uint256)50_storage", - "contract": "UUPSUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:107" + "contract": "ERC165Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\utils\\introspection\\ERC165Upgradeable.sol:41" }, { - "label": "transactions", + "label": "_roles", "offset": 0, "slot": "252", - "type": "t_mapping(t_uint256,t_struct(Transaction)8196_storage)", - "contract": "TalentLayerEscrow", - "src": "contracts/TalentLayerEscrow.sol:252" + "type": "t_mapping(t_bytes32,t_struct(RoleData)58_storage)", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\AccessControlUpgradeable.sol:61" }, { - "label": "platformIdToTokenToBalance", + "label": "__gap", "offset": 0, "slot": "253", - "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", - "contract": "TalentLayerEscrow", - "src": "contracts/TalentLayerEscrow.sol:261" + "type": "t_array(t_uint256)49_storage", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\AccessControlUpgradeable.sol:259" }, { - "label": "talentLayerServiceContract", + "label": "nextServiceId", "offset": 0, - "slot": "254", - "type": "t_contract(ITalentLayerService)15385", - "contract": "TalentLayerEscrow", - "src": "contracts/TalentLayerEscrow.sol:266" + "slot": "302", + "type": "t_uint256", + "contract": "TalentLayerServiceV1", + "src": "contracts\\archive\\TalentLayerServiceV1.sol:171" }, { - "label": "talentLayerIdContract", + "label": "tlId", "offset": 0, - "slot": "255", - "type": "t_contract(ITalentLayerID)15000", - "contract": "TalentLayerEscrow", - "src": "contracts/TalentLayerEscrow.sol:271" + "slot": "303", + "type": "t_contract(ITalentLayerID)19906", + "contract": "TalentLayerServiceV1", + "src": "contracts\\archive\\TalentLayerServiceV1.sol:176" }, { "label": "talentLayerPlatformIdContract", "offset": 0, - "slot": "256", - "type": "t_contract(ITalentLayerPlatformID)15212", - "contract": "TalentLayerEscrow", - "src": "contracts/TalentLayerEscrow.sol:276" + "slot": "304", + "type": "t_contract(ITalentLayerPlatformID)20118", + "contract": "TalentLayerServiceV1", + "src": "contracts\\archive\\TalentLayerServiceV1.sol:181" }, { - "label": "protocolWallet", + "label": "services", "offset": 0, - "slot": "257", - "type": "t_address_payable", - "contract": "TalentLayerEscrow", - "src": "contracts/TalentLayerEscrow.sol:281" + "slot": "305", + "type": "t_mapping(t_uint256,t_struct(Service)18364_storage)", + "contract": "TalentLayerServiceV1", + "src": "contracts\\archive\\TalentLayerServiceV1.sol:186" }, { - "label": "protocolEscrowFeeRate", - "offset": 20, - "slot": "257", - "type": "t_uint16", - "contract": "TalentLayerEscrow", - "src": "contracts/TalentLayerEscrow.sol:286" + "label": "proposals", + "offset": 0, + "slot": "306", + "type": "t_mapping(t_uint256,t_mapping(t_uint256,t_struct(Proposal)18380_storage))", + "contract": "TalentLayerServiceV1", + "src": "contracts\\archive\\TalentLayerServiceV1.sol:191" }, { - "label": "disputeIDtoTransactionID", + "label": "serviceNonce", "offset": 0, - "slot": "258", + "slot": "307", "type": "t_mapping(t_uint256,t_uint256)", - "contract": "TalentLayerEscrow", - "src": "contracts/TalentLayerEscrow.sol:316" + "contract": "TalentLayerServiceV1", + "src": "contracts\\archive\\TalentLayerServiceV1.sol:196" }, { - "label": "nextTransactionId", + "label": "proposalNonce", "offset": 0, - "slot": "259", - "type": "t_struct(Counter)3290_storage", - "contract": "TalentLayerEscrow", - "src": "contracts/TalentLayerEscrow.sol:321" + "slot": "308", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "TalentLayerServiceV1", + "src": "contracts\\archive\\TalentLayerServiceV1.sol:201" + }, + { + "label": "allowedTokenList", + "offset": 0, + "slot": "309", + "type": "t_mapping(t_address,t_struct(AllowedToken)18385_storage)", + "contract": "TalentLayerServiceV1", + "src": "contracts\\archive\\TalentLayerServiceV1.sol:206" + }, + { + "label": "minCompletionPercentage", + "offset": 0, + "slot": "310", + "type": "t_uint256", + "contract": "TalentLayerServiceV1", + "src": "contracts\\archive\\TalentLayerServiceV1.sol:211" } ], "types": { @@ -1644,10 +1808,6 @@ "label": "address", "numberOfBytes": "20" }, - "t_address_payable": { - "label": "address payable", - "numberOfBytes": "20" - }, "t_array(t_uint256)49_storage": { "label": "uint256[49]", "numberOfBytes": "1568" @@ -1660,34 +1820,34 @@ "label": "bool", "numberOfBytes": "1" }, - "t_bytes_storage": { - "label": "bytes", + "t_bytes32": { + "label": "bytes32", "numberOfBytes": "32" }, - "t_contract(Arbitrator)7789": { - "label": "contract Arbitrator", - "numberOfBytes": "20" - }, - "t_contract(ITalentLayerID)15000": { + "t_contract(ITalentLayerID)19906": { "label": "contract ITalentLayerID", "numberOfBytes": "20" }, - "t_contract(ITalentLayerPlatformID)15212": { + "t_contract(ITalentLayerPlatformID)20118": { "label": "contract ITalentLayerPlatformID", "numberOfBytes": "20" }, - "t_contract(ITalentLayerService)15385": { - "label": "contract ITalentLayerService", - "numberOfBytes": "20" + "t_enum(ProposalStatus)18350": { + "label": "enum TalentLayerServiceV1.ProposalStatus", + "members": [ + "Pending", + "Validated" + ], + "numberOfBytes": "1" }, - "t_enum(Status)8155": { - "label": "enum TalentLayerEscrow.Status", + "t_enum(Status)18347": { + "label": "enum TalentLayerServiceV1.Status", "members": [ - "NoDispute", - "WaitingSender", - "WaitingReceiver", - "DisputeCreated", - "Resolved" + "Opened", + "Confirmed", + "Finished", + "Cancelled", + "Uncompleted" ], "numberOfBytes": "1" }, @@ -1695,157 +1855,159 @@ "label": "mapping(address => bool)", "numberOfBytes": "32" }, - "t_mapping(t_address,t_uint256)": { - "label": "mapping(address => uint256)", + "t_mapping(t_address,t_struct(AllowedToken)18385_storage)": { + "label": "mapping(address => struct TalentLayerServiceV1.AllowedToken)", "numberOfBytes": "32" }, - "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { - "label": "mapping(uint256 => mapping(address => uint256))", + "t_mapping(t_bytes32,t_struct(RoleData)58_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", "numberOfBytes": "32" }, - "t_mapping(t_uint256,t_struct(Transaction)8196_storage)": { - "label": "mapping(uint256 => struct TalentLayerEscrow.Transaction)", + "t_mapping(t_uint256,t_mapping(t_uint256,t_struct(Proposal)18380_storage))": { + "label": "mapping(uint256 => mapping(uint256 => struct TalentLayerServiceV1.Proposal))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Proposal)18380_storage)": { + "label": "mapping(uint256 => struct TalentLayerServiceV1.Proposal)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Service)18364_storage)": { + "label": "mapping(uint256 => struct TalentLayerServiceV1.Service)", "numberOfBytes": "32" }, "t_mapping(t_uint256,t_uint256)": { "label": "mapping(uint256 => uint256)", "numberOfBytes": "32" }, - "t_struct(Counter)3290_storage": { - "label": "struct CountersUpgradeable.Counter", + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(AllowedToken)18385_storage": { + "label": "struct TalentLayerServiceV1.AllowedToken", "members": [ { - "label": "_value", - "type": "t_uint256", + "label": "isWhitelisted", + "type": "t_bool", "offset": 0, "slot": "0" + }, + { + "label": "minimumTransactionAmount", + "type": "t_uint256", + "offset": 0, + "slot": "1" } ], - "numberOfBytes": "32" + "numberOfBytes": "64" }, - "t_struct(Transaction)8196_storage": { - "label": "struct TalentLayerEscrow.Transaction", + "t_struct(Proposal)18380_storage": { + "label": "struct TalentLayerServiceV1.Proposal", "members": [ { - "label": "id", - "type": "t_uint256", + "label": "status", + "type": "t_enum(ProposalStatus)18350", "offset": 0, "slot": "0" }, { - "label": "sender", - "type": "t_address", + "label": "ownerId", + "type": "t_uint256", "offset": 0, "slot": "1" }, { - "label": "receiver", + "label": "rateToken", "type": "t_address", "offset": 0, "slot": "2" }, { - "label": "token", - "type": "t_address", + "label": "rateAmount", + "type": "t_uint256", "offset": 0, "slot": "3" }, { - "label": "amount", + "label": "platformId", "type": "t_uint256", "offset": 0, "slot": "4" }, { - "label": "releasedAmount", - "type": "t_uint256", + "label": "dataUri", + "type": "t_string_storage", "offset": 0, "slot": "5" }, { - "label": "serviceId", + "label": "expirationDate", "type": "t_uint256", "offset": 0, "slot": "6" - }, + } + ], + "numberOfBytes": "224" + }, + "t_struct(RoleData)58_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ { - "label": "proposalId", - "type": "t_uint256", + "label": "members", + "type": "t_mapping(t_address,t_bool)", "offset": 0, - "slot": "7" + "slot": "0" }, { - "label": "protocolEscrowFeeRate", - "type": "t_uint16", + "label": "adminRole", + "type": "t_bytes32", "offset": 0, - "slot": "8" - }, - { - "label": "originServiceFeeRate", - "type": "t_uint16", - "offset": 2, - "slot": "8" - }, - { - "label": "originValidatedProposalFeeRate", - "type": "t_uint16", - "offset": 4, - "slot": "8" - }, - { - "label": "arbitrator", - "type": "t_contract(Arbitrator)7789", - "offset": 6, - "slot": "8" - }, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Service)18364_storage": { + "label": "struct TalentLayerServiceV1.Service", + "members": [ { "label": "status", - "type": "t_enum(Status)8155", - "offset": 26, - "slot": "8" - }, - { - "label": "disputeId", - "type": "t_uint256", + "type": "t_enum(Status)18347", "offset": 0, - "slot": "9" + "slot": "0" }, { - "label": "senderFee", + "label": "ownerId", "type": "t_uint256", "offset": 0, - "slot": "10" + "slot": "1" }, { - "label": "receiverFee", + "label": "acceptedProposalId", "type": "t_uint256", "offset": 0, - "slot": "11" + "slot": "2" }, { - "label": "lastInteraction", - "type": "t_uint256", + "label": "dataUri", + "type": "t_string_storage", "offset": 0, - "slot": "12" + "slot": "3" }, { - "label": "arbitratorExtraData", - "type": "t_bytes_storage", + "label": "transactionId", + "type": "t_uint256", "offset": 0, - "slot": "13" + "slot": "4" }, { - "label": "arbitrationFeeTimeout", + "label": "platformId", "type": "t_uint256", "offset": 0, - "slot": "14" + "slot": "5" } ], - "numberOfBytes": "480" - }, - "t_uint16": { - "label": "uint16", - "numberOfBytes": "2" + "numberOfBytes": "192" }, "t_uint256": { "label": "uint256", @@ -1858,9 +2020,9 @@ } } }, - "452eb25e1c135f95b329252e20212c01eb69015592373af7097bb11bb44a9ae1": { - "address": "0xd726887633a87B4eC52633123681177e77bD02E1", - "txHash": "0xd90fb37bcdf965f0e7d897d12c206e8d68c30ea945d3b2a0bc022e0ed1dcf1c5", + "88ab1cdc37255e380eb6a7ab9e7ed0ef4fb8be10681fc961f9547c5db21335ec": { + "address": "0xF8d44F8cA3a601ea67B0f46D202E9a11C2768092", + "txHash": "0x66c44f1580ffd16727bf7004fece1e2740d1f3411afa4825682878c221907492", "layout": { "solcVersion": "0.8.17", "storage": [ @@ -1870,7 +2032,7 @@ "slot": "0", "type": "t_uint8", "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:62", "retypedFrom": "bool" }, { @@ -1879,7 +2041,7 @@ "slot": "0", "type": "t_bool", "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:67" }, { "label": "__gap", @@ -1887,183 +2049,159 @@ "slot": "1", "type": "t_array(t_uint256)50_storage", "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + "src": "@openzeppelin\\contracts-upgradeable\\utils\\ContextUpgradeable.sol:36" }, { - "label": "__gap", + "label": "_owner", "offset": 0, "slot": "51", - "type": "t_array(t_uint256)50_storage", - "contract": "ERC165Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:22" }, { - "label": "_name", + "label": "__gap", "offset": 0, - "slot": "101", - "type": "t_string_storage", - "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:25" - }, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:94" + }, { - "label": "_symbol", + "label": "_trustedForwarders", + "offset": 0, + "slot": "101", + "type": "t_mapping(t_address,t_bool)", + "contract": "ERC2771RecipientUpgradeable", + "src": "contracts\\libs\\ERC2771RecipientUpgradeable.sol:29" + }, + { + "label": "__gap", "offset": 0, "slot": "102", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC165Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\utils\\introspection\\ERC165Upgradeable.sol:41" + }, + { + "label": "_name", + "offset": 0, + "slot": "152", "type": "t_string_storage", "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:28" + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:25" + }, + { + "label": "_symbol", + "offset": 0, + "slot": "153", + "type": "t_string_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:28" }, { "label": "_owners", "offset": 0, - "slot": "103", + "slot": "154", "type": "t_mapping(t_uint256,t_address)", "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:31" + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:31" }, { "label": "_balances", "offset": 0, - "slot": "104", + "slot": "155", "type": "t_mapping(t_address,t_uint256)", "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:34" + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:34" }, { "label": "_tokenApprovals", "offset": 0, - "slot": "105", + "slot": "156", "type": "t_mapping(t_uint256,t_address)", "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:37" + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:37" }, { "label": "_operatorApprovals", "offset": 0, - "slot": "106", + "slot": "157", "type": "t_mapping(t_address,t_mapping(t_address,t_bool))", "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:40" + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:40" }, { "label": "__gap", "offset": 0, - "slot": "107", + "slot": "158", "type": "t_array(t_uint256)44_storage", "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:514" - }, - { - "label": "_roles", - "offset": 0, - "slot": "151", - "type": "t_mapping(t_bytes32,t_struct(RoleData)58_storage)", - "contract": "AccessControlUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61" - }, - { - "label": "__gap", - "offset": 0, - "slot": "152", - "type": "t_array(t_uint256)49_storage", - "contract": "AccessControlUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:259" + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:514" }, { "label": "__gap", "offset": 0, - "slot": "201", + "slot": "202", "type": "t_array(t_uint256)50_storage", "contract": "ERC1967UpgradeUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:211" + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\ERC1967\\ERC1967UpgradeUpgradeable.sol:211" }, { "label": "__gap", "offset": 0, - "slot": "251", + "slot": "252", "type": "t_array(t_uint256)50_storage", "contract": "UUPSUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:107" - }, - { - "label": "takenNames", - "offset": 0, - "slot": "301", - "type": "t_mapping(t_string_memory_ptr,t_bool)", - "contract": "TalentLayerPlatformID", - "src": "contracts/TalentLayerPlatformID.sol:65" + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\UUPSUpgradeable.sol:107" }, { - "label": "platforms", + "label": "nextReviewId", "offset": 0, "slot": "302", - "type": "t_mapping(t_uint256,t_struct(Platform)5970_storage)", - "contract": "TalentLayerPlatformID", - "src": "contracts/TalentLayerPlatformID.sol:70" + "type": "t_struct(Counter)3290_storage", + "contract": "TalentLayerReview", + "src": "contracts\\TalentLayerReview.sol:47" }, { - "label": "validArbitrators", + "label": "reviews", "offset": 0, "slot": "303", - "type": "t_mapping(t_address,t_bool)", - "contract": "TalentLayerPlatformID", - "src": "contracts/TalentLayerPlatformID.sol:75" + "type": "t_mapping(t_uint256,t_struct(Review)14071_storage)", + "contract": "TalentLayerReview", + "src": "contracts\\TalentLayerReview.sol:52" }, { - "label": "whitelist", + "label": "hasBuyerBeenReviewed", "offset": 0, "slot": "304", - "type": "t_mapping(t_address,t_bool)", - "contract": "TalentLayerPlatformID", - "src": "contracts/TalentLayerPlatformID.sol:80" + "type": "t_mapping(t_uint256,t_bool)", + "contract": "TalentLayerReview", + "src": "contracts\\TalentLayerReview.sol:57" }, { - "label": "internalArbitrators", + "label": "hasSellerBeenReviewed", "offset": 0, "slot": "305", - "type": "t_mapping(t_address,t_bool)", - "contract": "TalentLayerPlatformID", - "src": "contracts/TalentLayerPlatformID.sol:86" + "type": "t_mapping(t_uint256,t_bool)", + "contract": "TalentLayerReview", + "src": "contracts\\TalentLayerReview.sol:62" }, { - "label": "ids", + "label": "tlId", "offset": 0, "slot": "306", - "type": "t_mapping(t_address,t_uint256)", - "contract": "TalentLayerPlatformID", - "src": "contracts/TalentLayerPlatformID.sol:91" + "type": "t_contract(ITalentLayerID)16080", + "contract": "TalentLayerReview", + "src": "contracts\\TalentLayerReview.sol:67" }, { - "label": "mintFee", + "label": "talentLayerService", "offset": 0, "slot": "307", - "type": "t_uint256", - "contract": "TalentLayerPlatformID", - "src": "contracts/TalentLayerPlatformID.sol:96" - }, - { - "label": "minArbitrationFeeTimeout", - "offset": 0, - "slot": "308", - "type": "t_uint256", - "contract": "TalentLayerPlatformID", - "src": "contracts/TalentLayerPlatformID.sol:106" - }, - { - "label": "nextPlatformId", - "offset": 0, - "slot": "309", - "type": "t_struct(Counter)2768_storage", - "contract": "TalentLayerPlatformID", - "src": "contracts/TalentLayerPlatformID.sol:111" - }, - { - "label": "mintStatus", - "offset": 0, - "slot": "310", - "type": "t_enum(MintStatus)5946", - "contract": "TalentLayerPlatformID", - "src": "contracts/TalentLayerPlatformID.sol:116" + "type": "t_contract(ITalentLayerService)16465", + "contract": "TalentLayerReview", + "src": "contracts\\TalentLayerReview.sol:72" } ], "types": { @@ -2087,26 +2225,13 @@ "label": "bool", "numberOfBytes": "1" }, - "t_bytes32": { - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_bytes_storage": { - "label": "bytes", - "numberOfBytes": "32" - }, - "t_contract(Arbitrator)4644": { - "label": "contract Arbitrator", + "t_contract(ITalentLayerID)16080": { + "label": "contract ITalentLayerID", "numberOfBytes": "20" }, - "t_enum(MintStatus)5946": { - "label": "enum TalentLayerPlatformID.MintStatus", - "members": [ - "ON_PAUSE", - "ONLY_WHITELIST", - "PUBLIC" - ], - "numberOfBytes": "1" + "t_contract(ITalentLayerService)16465": { + "label": "contract ITalentLayerService", + "numberOfBytes": "20" }, "t_mapping(t_address,t_bool)": { "label": "mapping(address => bool)", @@ -2120,31 +2245,23 @@ "label": "mapping(address => uint256)", "numberOfBytes": "32" }, - "t_mapping(t_bytes32,t_struct(RoleData)58_storage)": { - "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", - "numberOfBytes": "32" - }, - "t_mapping(t_string_memory_ptr,t_bool)": { - "label": "mapping(string => bool)", - "numberOfBytes": "32" - }, "t_mapping(t_uint256,t_address)": { "label": "mapping(uint256 => address)", "numberOfBytes": "32" }, - "t_mapping(t_uint256,t_struct(Platform)5970_storage)": { - "label": "mapping(uint256 => struct TalentLayerPlatformID.Platform)", + "t_mapping(t_uint256,t_bool)": { + "label": "mapping(uint256 => bool)", "numberOfBytes": "32" }, - "t_string_memory_ptr": { - "label": "string", + "t_mapping(t_uint256,t_struct(Review)14071_storage)": { + "label": "mapping(uint256 => struct TalentLayerReview.Review)", "numberOfBytes": "32" }, "t_string_storage": { "label": "string", "numberOfBytes": "32" }, - "t_struct(Counter)2768_storage": { + "t_struct(Counter)3290_storage": { "label": "struct CountersUpgradeable.Counter", "members": [ { @@ -2156,8 +2273,8 @@ ], "numberOfBytes": "32" }, - "t_struct(Platform)5970_storage": { - "label": "struct TalentLayerPlatformID.Platform", + "t_struct(Review)14071_storage": { + "label": "struct TalentLayerReview.Review", "members": [ { "label": "id", @@ -2166,8 +2283,8 @@ "slot": "0" }, { - "label": "name", - "type": "t_string_storage", + "label": "ownerId", + "type": "t_uint256", "offset": 0, "slot": "1" }, @@ -2178,77 +2295,19 @@ "slot": "2" }, { - "label": "originServiceFeeRate", - "type": "t_uint16", + "label": "serviceId", + "type": "t_uint256", "offset": 0, "slot": "3" }, { - "label": "originValidatedProposalFeeRate", - "type": "t_uint16", - "offset": 2, - "slot": "3" - }, - { - "label": "servicePostingFee", + "label": "rating", "type": "t_uint256", "offset": 0, "slot": "4" - }, - { - "label": "proposalPostingFee", - "type": "t_uint256", - "offset": 0, - "slot": "5" - }, - { - "label": "arbitrator", - "type": "t_contract(Arbitrator)4644", - "offset": 0, - "slot": "6" - }, - { - "label": "arbitratorExtraData", - "type": "t_bytes_storage", - "offset": 0, - "slot": "7" - }, - { - "label": "arbitrationFeeTimeout", - "type": "t_uint256", - "offset": 0, - "slot": "8" - }, - { - "label": "signer", - "type": "t_address", - "offset": 0, - "slot": "9" - } - ], - "numberOfBytes": "320" - }, - "t_struct(RoleData)58_storage": { - "label": "struct AccessControlUpgradeable.RoleData", - "members": [ - { - "label": "members", - "type": "t_mapping(t_address,t_bool)", - "offset": 0, - "slot": "0" - }, - { - "label": "adminRole", - "type": "t_bytes32", - "offset": 0, - "slot": "1" } ], - "numberOfBytes": "64" - }, - "t_uint16": { - "label": "uint16", - "numberOfBytes": "2" + "numberOfBytes": "160" }, "t_uint256": { "label": "uint256", @@ -2261,9 +2320,9 @@ } } }, - "f9e7916a1c316964ab24794f96ac3ee47b57790f1fb37e7a459ebb7c82af0d2e": { - "address": "0x10f5FA91077E8F0Ce4791F998bFE7233216F7E76", - "txHash": "0x7446df365bae78c03532ab0e66f0b2943fddfb5bc45115fce95e90b5d72cc58b", + "09aac2d047d78f74214c535af98f3c37c37ef8536acce8b970ff6e54e333c9c1": { + "address": "0x05E4b5bA3c4E5e79e391CC11836751AaBA3e11D4", + "txHash": "0x5aad64c0c338ee115bd6bc17856fd8a3bf1d40ab715d0b04ca1af8aea0c1e25c", "layout": { "solcVersion": "0.8.17", "storage": [ @@ -2273,7 +2332,7 @@ "slot": "0", "type": "t_uint8", "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:62", "retypedFrom": "bool" }, { @@ -2282,7 +2341,7 @@ "slot": "0", "type": "t_bool", "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:67" }, { "label": "__gap", @@ -2290,7 +2349,7 @@ "slot": "1", "type": "t_array(t_uint256)50_storage", "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + "src": "@openzeppelin\\contracts-upgradeable\\utils\\ContextUpgradeable.sol:36" }, { "label": "_owner", @@ -2298,7 +2357,7 @@ "slot": "51", "type": "t_address", "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:22" }, { "label": "__gap", @@ -2306,7 +2365,7 @@ "slot": "52", "type": "t_array(t_uint256)49_storage", "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:94" }, { "label": "_trustedForwarders", @@ -2314,183 +2373,111 @@ "slot": "101", "type": "t_mapping(t_address,t_bool)", "contract": "ERC2771RecipientUpgradeable", - "src": "contracts/libs/ERC2771RecipientUpgradeable.sol:29" + "src": "contracts\\libs\\ERC2771RecipientUpgradeable.sol:29" }, { - "label": "__gap", + "label": "_paused", "offset": 0, "slot": "102", - "type": "t_array(t_uint256)50_storage", - "contract": "ERC165Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\security\\PausableUpgradeable.sol:29" }, { - "label": "_name", + "label": "__gap", "offset": 0, - "slot": "152", - "type": "t_string_storage", - "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:25" - }, - { - "label": "_symbol", - "offset": 0, - "slot": "153", - "type": "t_string_storage", - "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:28" - }, - { - "label": "_owners", - "offset": 0, - "slot": "154", - "type": "t_mapping(t_uint256,t_address)", - "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:31" - }, - { - "label": "_balances", - "offset": 0, - "slot": "155", - "type": "t_mapping(t_address,t_uint256)", - "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:34" - }, - { - "label": "_tokenApprovals", - "offset": 0, - "slot": "156", - "type": "t_mapping(t_uint256,t_address)", - "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:37" - }, - { - "label": "_operatorApprovals", - "offset": 0, - "slot": "157", - "type": "t_mapping(t_address,t_mapping(t_address,t_bool))", - "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:40" - }, - { - "label": "__gap", - "offset": 0, - "slot": "158", - "type": "t_array(t_uint256)44_storage", - "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:514" + "slot": "103", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\security\\PausableUpgradeable.sol:116" }, { "label": "__gap", "offset": 0, - "slot": "202", + "slot": "152", "type": "t_array(t_uint256)50_storage", "contract": "ERC1967UpgradeUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:211" + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\ERC1967\\ERC1967UpgradeUpgradeable.sol:211" }, { "label": "__gap", "offset": 0, - "slot": "252", + "slot": "202", "type": "t_array(t_uint256)50_storage", "contract": "UUPSUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:107" - }, - { - "label": "talentLayerPlatformIdContract", - "offset": 0, - "slot": "302", - "type": "t_contract(ITalentLayerPlatformID)7478", - "contract": "TalentLayerID", - "src": "contracts/TalentLayerID.sol:70" - }, - { - "label": "takenHandles", - "offset": 0, - "slot": "303", - "type": "t_mapping(t_string_memory_ptr,t_bool)", - "contract": "TalentLayerID", - "src": "contracts/TalentLayerID.sol:75" - }, - { - "label": "profiles", - "offset": 0, - "slot": "304", - "type": "t_mapping(t_uint256,t_struct(Profile)4707_storage)", - "contract": "TalentLayerID", - "src": "contracts/TalentLayerID.sol:80" + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\UUPSUpgradeable.sol:107" }, { - "label": "ids", + "label": "transactions", "offset": 0, - "slot": "305", - "type": "t_mapping(t_address,t_uint256)", - "contract": "TalentLayerID", - "src": "contracts/TalentLayerID.sol:85" + "slot": "252", + "type": "t_mapping(t_uint256,t_struct(Transaction)2281_storage)", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:252" }, { - "label": "mintFee", + "label": "platformIdToTokenToBalance", "offset": 0, - "slot": "306", - "type": "t_uint256", - "contract": "TalentLayerID", - "src": "contracts/TalentLayerID.sol:90" + "slot": "253", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:261" }, { - "label": "nextProfileId", + "label": "talentLayerServiceContract", "offset": 0, - "slot": "307", - "type": "t_struct(Counter)2768_storage", - "contract": "TalentLayerID", - "src": "contracts/TalentLayerID.sol:95" + "slot": "254", + "type": "t_contract(ITalentLayerService)4997", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:266" }, { - "label": "delegates", + "label": "talentLayerIdContract", "offset": 0, - "slot": "308", - "type": "t_mapping(t_uint256,t_mapping(t_address,t_bool))", - "contract": "TalentLayerID", - "src": "contracts/TalentLayerID.sol:100" + "slot": "255", + "type": "t_contract(ITalentLayerID)4648", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:271" }, { - "label": "whitelistMerkleRoot", + "label": "talentLayerPlatformIdContract", "offset": 0, - "slot": "309", - "type": "t_bytes32", - "contract": "TalentLayerID", - "src": "contracts/TalentLayerID.sol:105" + "slot": "256", + "type": "t_contract(ITalentLayerPlatformID)4860", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:276" }, { - "label": "mintStatus", + "label": "protocolWallet", "offset": 0, - "slot": "310", - "type": "t_enum(MintStatus)4698", - "contract": "TalentLayerID", - "src": "contracts/TalentLayerID.sol:110" + "slot": "257", + "type": "t_address_payable", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:281" }, { - "label": "shortHandlesMaxPrice", - "offset": 0, - "slot": "311", - "type": "t_uint256", - "contract": "TalentLayerID", - "src": "contracts/TalentLayerID.sol:115" + "label": "protocolEscrowFeeRate", + "offset": 20, + "slot": "257", + "type": "t_uint16", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:286" }, { - "label": "hasActivity", + "label": "disputeIDtoTransactionID", "offset": 0, - "slot": "312", - "type": "t_mapping(t_uint256,t_bool)", - "contract": "TalentLayerID", - "src": "contracts/TalentLayerID.sol:120" + "slot": "258", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:316" }, { - "label": "isServiceContract", + "label": "nextTransactionId", "offset": 0, - "slot": "313", - "type": "t_mapping(t_address,t_bool)", - "contract": "TalentLayerID", - "src": "contracts/TalentLayerID.sol:125" + "slot": "259", + "type": "t_struct(Counter)1819_storage", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:321" } ], "types": { @@ -2498,9 +2485,9 @@ "label": "address", "numberOfBytes": "20" }, - "t_array(t_uint256)44_storage": { - "label": "uint256[44]", - "numberOfBytes": "1408" + "t_address_payable": { + "label": "address payable", + "numberOfBytes": "20" }, "t_array(t_uint256)49_storage": { "label": "uint256[49]", @@ -2514,20 +2501,34 @@ "label": "bool", "numberOfBytes": "1" }, - "t_bytes32": { - "label": "bytes32", + "t_bytes_storage": { + "label": "bytes", "numberOfBytes": "32" }, - "t_contract(ITalentLayerPlatformID)7478": { + "t_contract(Arbitrator)2187": { + "label": "contract Arbitrator", + "numberOfBytes": "20" + }, + "t_contract(ITalentLayerID)4648": { + "label": "contract ITalentLayerID", + "numberOfBytes": "20" + }, + "t_contract(ITalentLayerPlatformID)4860": { "label": "contract ITalentLayerPlatformID", "numberOfBytes": "20" }, - "t_enum(MintStatus)4698": { - "label": "enum TalentLayerID.MintStatus", + "t_contract(ITalentLayerService)4997": { + "label": "contract ITalentLayerService", + "numberOfBytes": "20" + }, + "t_enum(Status)2240": { + "label": "enum TalentLayerEscrow.Status", "members": [ - "ON_PAUSE", - "ONLY_WHITELIST", - "PUBLIC" + "NoDispute", + "WaitingSender", + "WaitingReceiver", + "DisputeCreated", + "Resolved" ], "numberOfBytes": "1" }, @@ -2535,43 +2536,23 @@ "label": "mapping(address => bool)", "numberOfBytes": "32" }, - "t_mapping(t_address,t_mapping(t_address,t_bool))": { - "label": "mapping(address => mapping(address => bool))", - "numberOfBytes": "32" - }, "t_mapping(t_address,t_uint256)": { "label": "mapping(address => uint256)", "numberOfBytes": "32" }, - "t_mapping(t_string_memory_ptr,t_bool)": { - "label": "mapping(string => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_address)": { - "label": "mapping(uint256 => address)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_bool)": { - "label": "mapping(uint256 => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_mapping(t_address,t_bool))": { - "label": "mapping(uint256 => mapping(address => bool))", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_struct(Profile)4707_storage)": { - "label": "mapping(uint256 => struct TalentLayerID.Profile)", + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "label": "mapping(uint256 => mapping(address => uint256))", "numberOfBytes": "32" }, - "t_string_memory_ptr": { - "label": "string", + "t_mapping(t_uint256,t_struct(Transaction)2281_storage)": { + "label": "mapping(uint256 => struct TalentLayerEscrow.Transaction)", "numberOfBytes": "32" }, - "t_string_storage": { - "label": "string", + "t_mapping(t_uint256,t_uint256)": { + "label": "mapping(uint256 => uint256)", "numberOfBytes": "32" }, - "t_struct(Counter)2768_storage": { + "t_struct(Counter)1819_storage": { "label": "struct CountersUpgradeable.Counter", "members": [ { @@ -2583,8 +2564,8 @@ ], "numberOfBytes": "32" }, - "t_struct(Profile)4707_storage": { - "label": "struct TalentLayerID.Profile", + "t_struct(Transaction)2281_storage": { + "label": "struct TalentLayerEscrow.Transaction", "members": [ { "label": "id", @@ -2593,25 +2574,1735 @@ "slot": "0" }, { - "label": "handle", - "type": "t_string_storage", + "label": "sender", + "type": "t_address", "offset": 0, "slot": "1" }, { - "label": "platformId", - "type": "t_uint256", + "label": "receiver", + "type": "t_address", "offset": 0, "slot": "2" }, { - "label": "dataUri", - "type": "t_string_storage", + "label": "token", + "type": "t_address", "offset": 0, "slot": "3" - } - ], - "numberOfBytes": "128" + }, + { + "label": "amount", + "type": "t_uint256", + "offset": 0, + "slot": "4" + }, + { + "label": "releasedAmount", + "type": "t_uint256", + "offset": 0, + "slot": "5" + }, + { + "label": "serviceId", + "type": "t_uint256", + "offset": 0, + "slot": "6" + }, + { + "label": "proposalId", + "type": "t_uint256", + "offset": 0, + "slot": "7" + }, + { + "label": "protocolEscrowFeeRate", + "type": "t_uint16", + "offset": 0, + "slot": "8" + }, + { + "label": "originServiceFeeRate", + "type": "t_uint16", + "offset": 2, + "slot": "8" + }, + { + "label": "originValidatedProposalFeeRate", + "type": "t_uint16", + "offset": 4, + "slot": "8" + }, + { + "label": "arbitrator", + "type": "t_contract(Arbitrator)2187", + "offset": 6, + "slot": "8" + }, + { + "label": "status", + "type": "t_enum(Status)2240", + "offset": 26, + "slot": "8" + }, + { + "label": "disputeId", + "type": "t_uint256", + "offset": 0, + "slot": "9" + }, + { + "label": "senderFee", + "type": "t_uint256", + "offset": 0, + "slot": "10" + }, + { + "label": "receiverFee", + "type": "t_uint256", + "offset": 0, + "slot": "11" + }, + { + "label": "lastInteraction", + "type": "t_uint256", + "offset": 0, + "slot": "12" + }, + { + "label": "arbitratorExtraData", + "type": "t_bytes_storage", + "offset": 0, + "slot": "13" + }, + { + "label": "arbitrationFeeTimeout", + "type": "t_uint256", + "offset": 0, + "slot": "14" + } + ], + "numberOfBytes": "480" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "5b077d0944a30c4d3208cf540374f4ebf661e5ef8fae32acd57c36364fe3c7ea": { + "address": "0xd3b709d2E6923BbfDC83e990a5b0c41e4aD1e3fA", + "txHash": "0x066fe906af4ae05df1a058fbaea43c83c4a1fee1c0f05ca36d5b0189847e5deb", + "layout": { + "solcVersion": "0.8.17", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\utils\\ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:94" + }, + { + "label": "_trustedForwarders", + "offset": 0, + "slot": "101", + "type": "t_mapping(t_address,t_bool)", + "contract": "ERC2771RecipientUpgradeable", + "src": "contracts\\libs\\ERC2771RecipientUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\ERC1967\\ERC1967UpgradeUpgradeable.sol:211" + }, + { + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\UUPSUpgradeable.sol:107" + }, + { + "label": "__gap", + "offset": 0, + "slot": "202", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC165Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\utils\\introspection\\ERC165Upgradeable.sol:41" + }, + { + "label": "_roles", + "offset": 0, + "slot": "252", + "type": "t_mapping(t_bytes32,t_struct(RoleData)58_storage)", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\AccessControlUpgradeable.sol:61" + }, + { + "label": "__gap", + "offset": 0, + "slot": "253", + "type": "t_array(t_uint256)49_storage", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\AccessControlUpgradeable.sol:259" + }, + { + "label": "nextServiceId", + "offset": 0, + "slot": "302", + "type": "t_uint256", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:187" + }, + { + "label": "tlId", + "offset": 0, + "slot": "303", + "type": "t_contract(ITalentLayerID)9584", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:192" + }, + { + "label": "talentLayerPlatformIdContract", + "offset": 0, + "slot": "304", + "type": "t_contract(ITalentLayerPlatformID)9796", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:197" + }, + { + "label": "services", + "offset": 0, + "slot": "305", + "type": "t_mapping(t_uint256,t_struct(Service)8116_storage)", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:202" + }, + { + "label": "proposals", + "offset": 0, + "slot": "306", + "type": "t_mapping(t_uint256,t_mapping(t_uint256,t_struct(Proposal)8134_storage))", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:207" + }, + { + "label": "serviceNonce", + "offset": 0, + "slot": "307", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:212" + }, + { + "label": "proposalNonce", + "offset": 0, + "slot": "308", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:217" + }, + { + "label": "allowedTokenList", + "offset": 0, + "slot": "309", + "type": "t_mapping(t_address,t_struct(AllowedToken)8139_storage)", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:222" + }, + { + "label": "minCompletionPercentage", + "offset": 0, + "slot": "310", + "type": "t_uint256", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:227" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(ITalentLayerID)9584": { + "label": "contract ITalentLayerID", + "numberOfBytes": "20" + }, + "t_contract(ITalentLayerPlatformID)9796": { + "label": "contract ITalentLayerPlatformID", + "numberOfBytes": "20" + }, + "t_enum(ProposalStatus)8098": { + "label": "enum TalentLayerService.ProposalStatus", + "members": [ + "Pending", + "Validated" + ], + "numberOfBytes": "1" + }, + "t_enum(Status)8095": { + "label": "enum TalentLayerService.Status", + "members": [ + "Opened", + "Confirmed", + "Finished", + "Cancelled", + "Uncompleted" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(AllowedToken)8139_storage)": { + "label": "mapping(address => struct TalentLayerService.AllowedToken)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_struct(RoleData)58_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_uint256,t_struct(Proposal)8134_storage))": { + "label": "mapping(uint256 => mapping(uint256 => struct TalentLayerService.Proposal))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Proposal)8134_storage)": { + "label": "mapping(uint256 => struct TalentLayerService.Proposal)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Service)8116_storage)": { + "label": "mapping(uint256 => struct TalentLayerService.Service)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_uint256)": { + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(AllowedToken)8139_storage": { + "label": "struct TalentLayerService.AllowedToken", + "members": [ + { + "label": "isWhitelisted", + "type": "t_bool", + "offset": 0, + "slot": "0" + }, + { + "label": "minimumTransactionAmount", + "type": "t_uint256", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Proposal)8134_storage": { + "label": "struct TalentLayerService.Proposal", + "members": [ + { + "label": "status", + "type": "t_enum(ProposalStatus)8098", + "offset": 0, + "slot": "0" + }, + { + "label": "ownerId", + "type": "t_uint256", + "offset": 0, + "slot": "1" + }, + { + "label": "rateToken", + "type": "t_address", + "offset": 0, + "slot": "2" + }, + { + "label": "rateAmount", + "type": "t_uint256", + "offset": 0, + "slot": "3" + }, + { + "label": "platformId", + "type": "t_uint256", + "offset": 0, + "slot": "4" + }, + { + "label": "dataUri", + "type": "t_string_storage", + "offset": 0, + "slot": "5" + }, + { + "label": "expirationDate", + "type": "t_uint256", + "offset": 0, + "slot": "6" + }, + { + "label": "referrerId", + "type": "t_uint256", + "offset": 0, + "slot": "7" + } + ], + "numberOfBytes": "256" + }, + "t_struct(RoleData)58_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)", + "offset": 0, + "slot": "0" + }, + { + "label": "adminRole", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Service)8116_storage": { + "label": "struct TalentLayerService.Service", + "members": [ + { + "label": "status", + "type": "t_enum(Status)8095", + "offset": 0, + "slot": "0" + }, + { + "label": "ownerId", + "type": "t_uint256", + "offset": 0, + "slot": "1" + }, + { + "label": "acceptedProposalId", + "type": "t_uint256", + "offset": 0, + "slot": "2" + }, + { + "label": "dataUri", + "type": "t_string_storage", + "offset": 0, + "slot": "3" + }, + { + "label": "transactionId", + "type": "t_uint256", + "offset": 0, + "slot": "4" + }, + { + "label": "platformId", + "type": "t_uint256", + "offset": 0, + "slot": "5" + }, + { + "label": "rateToken", + "type": "t_address", + "offset": 0, + "slot": "6" + }, + { + "label": "referralAmount", + "type": "t_uint256", + "offset": 0, + "slot": "7" + } + ], + "numberOfBytes": "256" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "a67d6aa882378162466d32952b5a0b9cbf10b9f0703e2e848749a07767f34ba2": { + "address": "0x1060a19A5Cee808ab120616ef2399983cB27A1A3", + "txHash": "0x893a5a32457797c1340e2d9d63ade6fa85c4ff19111047d73db9b95e629817a0", + "layout": { + "solcVersion": "0.8.17", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\utils\\ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:94" + }, + { + "label": "_trustedForwarders", + "offset": 0, + "slot": "101", + "type": "t_mapping(t_address,t_bool)", + "contract": "ERC2771RecipientUpgradeable", + "src": "contracts\\libs\\ERC2771RecipientUpgradeable.sol:29" + }, + { + "label": "_paused", + "offset": 0, + "slot": "102", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\security\\PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "103", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\security\\PausableUpgradeable.sol:116" + }, + { + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\ERC1967\\ERC1967UpgradeUpgradeable.sol:211" + }, + { + "label": "__gap", + "offset": 0, + "slot": "202", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\UUPSUpgradeable.sol:107" + }, + { + "label": "transactions", + "offset": 0, + "slot": "252", + "type": "t_mapping(t_uint256,t_struct(Transaction)2287_storage)", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:280" + }, + { + "label": "platformIdToTokenToBalance", + "offset": 0, + "slot": "253", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:289" + }, + { + "label": "talentLayerServiceContract", + "offset": 0, + "slot": "254", + "type": "t_contract(ITalentLayerService)5225", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:294" + }, + { + "label": "talentLayerIdContract", + "offset": 0, + "slot": "255", + "type": "t_contract(ITalentLayerID)4855", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:299" + }, + { + "label": "talentLayerPlatformIdContract", + "offset": 0, + "slot": "256", + "type": "t_contract(ITalentLayerPlatformID)5067", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:304" + }, + { + "label": "protocolWallet", + "offset": 0, + "slot": "257", + "type": "t_address_payable", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:309" + }, + { + "label": "protocolEscrowFeeRate", + "offset": 20, + "slot": "257", + "type": "t_uint16", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:314" + }, + { + "label": "disputeIDtoTransactionID", + "offset": 0, + "slot": "258", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:344" + }, + { + "label": "nextTransactionId", + "offset": 0, + "slot": "259", + "type": "t_struct(Counter)1819_storage", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:349" + }, + { + "label": "referrerIdToTokenToBalance", + "offset": 0, + "slot": "260", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:357" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_address_payable": { + "label": "address payable", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes_storage": { + "label": "bytes", + "numberOfBytes": "32" + }, + "t_contract(Arbitrator)2187": { + "label": "contract Arbitrator", + "numberOfBytes": "20" + }, + "t_contract(ITalentLayerID)4855": { + "label": "contract ITalentLayerID", + "numberOfBytes": "20" + }, + "t_contract(ITalentLayerPlatformID)5067": { + "label": "contract ITalentLayerPlatformID", + "numberOfBytes": "20" + }, + "t_contract(ITalentLayerService)5225": { + "label": "contract ITalentLayerService", + "numberOfBytes": "20" + }, + "t_enum(Status)2240": { + "label": "enum TalentLayerEscrow.Status", + "members": [ + "NoDispute", + "WaitingSender", + "WaitingReceiver", + "DisputeCreated", + "Resolved" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Transaction)2287_storage)": { + "label": "mapping(uint256 => struct TalentLayerEscrow.Transaction)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_uint256)": { + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32" + }, + "t_struct(Counter)1819_storage": { + "label": "struct CountersUpgradeable.Counter", + "members": [ + { + "label": "_value", + "type": "t_uint256", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(Transaction)2287_storage": { + "label": "struct TalentLayerEscrow.Transaction", + "members": [ + { + "label": "id", + "type": "t_uint256", + "offset": 0, + "slot": "0" + }, + { + "label": "sender", + "type": "t_address", + "offset": 0, + "slot": "1" + }, + { + "label": "receiver", + "type": "t_address", + "offset": 0, + "slot": "2" + }, + { + "label": "token", + "type": "t_address", + "offset": 0, + "slot": "3" + }, + { + "label": "amount", + "type": "t_uint256", + "offset": 0, + "slot": "4" + }, + { + "label": "releasedAmount", + "type": "t_uint256", + "offset": 0, + "slot": "5" + }, + { + "label": "serviceId", + "type": "t_uint256", + "offset": 0, + "slot": "6" + }, + { + "label": "proposalId", + "type": "t_uint256", + "offset": 0, + "slot": "7" + }, + { + "label": "protocolEscrowFeeRate", + "type": "t_uint16", + "offset": 0, + "slot": "8" + }, + { + "label": "originServiceFeeRate", + "type": "t_uint16", + "offset": 2, + "slot": "8" + }, + { + "label": "originValidatedProposalFeeRate", + "type": "t_uint16", + "offset": 4, + "slot": "8" + }, + { + "label": "arbitrator", + "type": "t_contract(Arbitrator)2187", + "offset": 6, + "slot": "8" + }, + { + "label": "status", + "type": "t_enum(Status)2240", + "offset": 26, + "slot": "8" + }, + { + "label": "disputeId", + "type": "t_uint256", + "offset": 0, + "slot": "9" + }, + { + "label": "senderFee", + "type": "t_uint256", + "offset": 0, + "slot": "10" + }, + { + "label": "receiverFee", + "type": "t_uint256", + "offset": 0, + "slot": "11" + }, + { + "label": "lastInteraction", + "type": "t_uint256", + "offset": 0, + "slot": "12" + }, + { + "label": "arbitratorExtraData", + "type": "t_bytes_storage", + "offset": 0, + "slot": "13" + }, + { + "label": "arbitrationFeeTimeout", + "type": "t_uint256", + "offset": 0, + "slot": "14" + }, + { + "label": "referrerId", + "type": "t_uint256", + "offset": 0, + "slot": "15" + }, + { + "label": "referralAmount", + "type": "t_uint256", + "offset": 0, + "slot": "16" + }, + { + "label": "totalAmount", + "type": "t_uint256", + "offset": 0, + "slot": "17" + } + ], + "numberOfBytes": "576" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "f294cc7eef142927d49f0c558eb78063d4cb38921116d44b1f3f437e0ce75a94": { + "address": "0x4e644D65cFa49C4F9431659369AD3a7809E065aa", + "txHash": "0xb4fc739de1532e08bd656895967aea3e52439c0320413fdc04b925d3b6dc1c27", + "layout": { + "solcVersion": "0.8.17", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\utils\\ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:94" + }, + { + "label": "_trustedForwarders", + "offset": 0, + "slot": "101", + "type": "t_mapping(t_address,t_bool)", + "contract": "ERC2771RecipientUpgradeable", + "src": "contracts\\libs\\ERC2771RecipientUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\ERC1967\\ERC1967UpgradeUpgradeable.sol:211" + }, + { + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\UUPSUpgradeable.sol:107" + }, + { + "label": "__gap", + "offset": 0, + "slot": "202", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC165Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\utils\\introspection\\ERC165Upgradeable.sol:41" + }, + { + "label": "_roles", + "offset": 0, + "slot": "252", + "type": "t_mapping(t_bytes32,t_struct(RoleData)58_storage)", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\AccessControlUpgradeable.sol:61" + }, + { + "label": "__gap", + "offset": 0, + "slot": "253", + "type": "t_array(t_uint256)49_storage", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\AccessControlUpgradeable.sol:259" + }, + { + "label": "nextServiceId", + "offset": 0, + "slot": "302", + "type": "t_uint256", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:187" + }, + { + "label": "tlId", + "offset": 0, + "slot": "303", + "type": "t_contract(ITalentLayerID)4885", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:192" + }, + { + "label": "talentLayerPlatformIdContract", + "offset": 0, + "slot": "304", + "type": "t_contract(ITalentLayerPlatformID)5097", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:197" + }, + { + "label": "services", + "offset": 0, + "slot": "305", + "type": "t_mapping(t_uint256,t_struct(Service)3417_storage)", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:202" + }, + { + "label": "proposals", + "offset": 0, + "slot": "306", + "type": "t_mapping(t_uint256,t_mapping(t_uint256,t_struct(Proposal)3435_storage))", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:207" + }, + { + "label": "serviceNonce", + "offset": 0, + "slot": "307", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:212" + }, + { + "label": "proposalNonce", + "offset": 0, + "slot": "308", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:217" + }, + { + "label": "allowedTokenList", + "offset": 0, + "slot": "309", + "type": "t_mapping(t_address,t_struct(AllowedToken)3440_storage)", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:222" + }, + { + "label": "minCompletionPercentage", + "offset": 0, + "slot": "310", + "type": "t_uint256", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:227" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(ITalentLayerID)4885": { + "label": "contract ITalentLayerID", + "numberOfBytes": "20" + }, + "t_contract(ITalentLayerPlatformID)5097": { + "label": "contract ITalentLayerPlatformID", + "numberOfBytes": "20" + }, + "t_enum(ProposalStatus)3399": { + "label": "enum TalentLayerService.ProposalStatus", + "members": [ + "Pending", + "Validated" + ], + "numberOfBytes": "1" + }, + "t_enum(Status)3396": { + "label": "enum TalentLayerService.Status", + "members": [ + "Opened", + "Confirmed", + "Finished", + "Cancelled", + "Uncompleted" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(AllowedToken)3440_storage)": { + "label": "mapping(address => struct TalentLayerService.AllowedToken)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_struct(RoleData)58_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_uint256,t_struct(Proposal)3435_storage))": { + "label": "mapping(uint256 => mapping(uint256 => struct TalentLayerService.Proposal))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Proposal)3435_storage)": { + "label": "mapping(uint256 => struct TalentLayerService.Proposal)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Service)3417_storage)": { + "label": "mapping(uint256 => struct TalentLayerService.Service)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_uint256)": { + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(AllowedToken)3440_storage": { + "label": "struct TalentLayerService.AllowedToken", + "members": [ + { + "label": "isWhitelisted", + "type": "t_bool", + "offset": 0, + "slot": "0" + }, + { + "label": "minimumTransactionAmount", + "type": "t_uint256", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Proposal)3435_storage": { + "label": "struct TalentLayerService.Proposal", + "members": [ + { + "label": "status", + "type": "t_enum(ProposalStatus)3399", + "offset": 0, + "slot": "0" + }, + { + "label": "ownerId", + "type": "t_uint256", + "offset": 0, + "slot": "1" + }, + { + "label": "rateToken", + "type": "t_address", + "offset": 0, + "slot": "2" + }, + { + "label": "rateAmount", + "type": "t_uint256", + "offset": 0, + "slot": "3" + }, + { + "label": "platformId", + "type": "t_uint256", + "offset": 0, + "slot": "4" + }, + { + "label": "dataUri", + "type": "t_string_storage", + "offset": 0, + "slot": "5" + }, + { + "label": "expirationDate", + "type": "t_uint256", + "offset": 0, + "slot": "6" + }, + { + "label": "referrerId", + "type": "t_uint256", + "offset": 0, + "slot": "7" + } + ], + "numberOfBytes": "256" + }, + "t_struct(RoleData)58_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)", + "offset": 0, + "slot": "0" + }, + { + "label": "adminRole", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Service)3417_storage": { + "label": "struct TalentLayerService.Service", + "members": [ + { + "label": "status", + "type": "t_enum(Status)3396", + "offset": 0, + "slot": "0" + }, + { + "label": "ownerId", + "type": "t_uint256", + "offset": 0, + "slot": "1" + }, + { + "label": "acceptedProposalId", + "type": "t_uint256", + "offset": 0, + "slot": "2" + }, + { + "label": "dataUri", + "type": "t_string_storage", + "offset": 0, + "slot": "3" + }, + { + "label": "transactionId", + "type": "t_uint256", + "offset": 0, + "slot": "4" + }, + { + "label": "platformId", + "type": "t_uint256", + "offset": 0, + "slot": "5" + }, + { + "label": "rateToken", + "type": "t_address", + "offset": 0, + "slot": "6" + }, + { + "label": "referralAmount", + "type": "t_uint256", + "offset": 0, + "slot": "7" + } + ], + "numberOfBytes": "256" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "a442464e95ddd6d4eb5a195f3edcbab69d12df336c03a47e889ae54493f98ad1": { + "address": "0x6A630D781aD6cf0D695E8863C264E057F842C768", + "txHash": "0xe495f2b64c8601daff852d7c8a294e6523c3be117044a0c73f2ef1bd9260378b", + "layout": { + "solcVersion": "0.8.17", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\utils\\ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:94" + }, + { + "label": "_trustedForwarders", + "offset": 0, + "slot": "101", + "type": "t_mapping(t_address,t_bool)", + "contract": "ERC2771RecipientUpgradeable", + "src": "contracts\\libs\\ERC2771RecipientUpgradeable.sol:29" + }, + { + "label": "_paused", + "offset": 0, + "slot": "102", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\security\\PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "103", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\security\\PausableUpgradeable.sol:116" + }, + { + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\ERC1967\\ERC1967UpgradeUpgradeable.sol:211" + }, + { + "label": "__gap", + "offset": 0, + "slot": "202", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\UUPSUpgradeable.sol:107" + }, + { + "label": "transactions", + "offset": 0, + "slot": "252", + "type": "t_mapping(t_uint256,t_struct(Transaction)2287_storage)", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:280" + }, + { + "label": "platformIdToTokenToBalance", + "offset": 0, + "slot": "253", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:289" + }, + { + "label": "talentLayerServiceContract", + "offset": 0, + "slot": "254", + "type": "t_contract(ITalentLayerService)5231", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:294" + }, + { + "label": "talentLayerIdContract", + "offset": 0, + "slot": "255", + "type": "t_contract(ITalentLayerID)4861", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:299" + }, + { + "label": "talentLayerPlatformIdContract", + "offset": 0, + "slot": "256", + "type": "t_contract(ITalentLayerPlatformID)5073", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:304" + }, + { + "label": "protocolWallet", + "offset": 0, + "slot": "257", + "type": "t_address_payable", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:309" + }, + { + "label": "protocolEscrowFeeRate", + "offset": 20, + "slot": "257", + "type": "t_uint16", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:314" + }, + { + "label": "disputeIDtoTransactionID", + "offset": 0, + "slot": "258", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:344" + }, + { + "label": "nextTransactionId", + "offset": 0, + "slot": "259", + "type": "t_struct(Counter)1819_storage", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:349" + }, + { + "label": "referrerIdToTokenToBalance", + "offset": 0, + "slot": "260", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:357" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_address_payable": { + "label": "address payable", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes_storage": { + "label": "bytes", + "numberOfBytes": "32" + }, + "t_contract(Arbitrator)2187": { + "label": "contract Arbitrator", + "numberOfBytes": "20" + }, + "t_contract(ITalentLayerID)4861": { + "label": "contract ITalentLayerID", + "numberOfBytes": "20" + }, + "t_contract(ITalentLayerPlatformID)5073": { + "label": "contract ITalentLayerPlatformID", + "numberOfBytes": "20" + }, + "t_contract(ITalentLayerService)5231": { + "label": "contract ITalentLayerService", + "numberOfBytes": "20" + }, + "t_enum(Status)2240": { + "label": "enum TalentLayerEscrow.Status", + "members": [ + "NoDispute", + "WaitingSender", + "WaitingReceiver", + "DisputeCreated", + "Resolved" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Transaction)2287_storage)": { + "label": "mapping(uint256 => struct TalentLayerEscrow.Transaction)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_uint256)": { + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32" + }, + "t_struct(Counter)1819_storage": { + "label": "struct CountersUpgradeable.Counter", + "members": [ + { + "label": "_value", + "type": "t_uint256", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(Transaction)2287_storage": { + "label": "struct TalentLayerEscrow.Transaction", + "members": [ + { + "label": "id", + "type": "t_uint256", + "offset": 0, + "slot": "0" + }, + { + "label": "sender", + "type": "t_address", + "offset": 0, + "slot": "1" + }, + { + "label": "receiver", + "type": "t_address", + "offset": 0, + "slot": "2" + }, + { + "label": "token", + "type": "t_address", + "offset": 0, + "slot": "3" + }, + { + "label": "amount", + "type": "t_uint256", + "offset": 0, + "slot": "4" + }, + { + "label": "releasedAmount", + "type": "t_uint256", + "offset": 0, + "slot": "5" + }, + { + "label": "serviceId", + "type": "t_uint256", + "offset": 0, + "slot": "6" + }, + { + "label": "proposalId", + "type": "t_uint256", + "offset": 0, + "slot": "7" + }, + { + "label": "protocolEscrowFeeRate", + "type": "t_uint16", + "offset": 0, + "slot": "8" + }, + { + "label": "originServiceFeeRate", + "type": "t_uint16", + "offset": 2, + "slot": "8" + }, + { + "label": "originValidatedProposalFeeRate", + "type": "t_uint16", + "offset": 4, + "slot": "8" + }, + { + "label": "arbitrator", + "type": "t_contract(Arbitrator)2187", + "offset": 6, + "slot": "8" + }, + { + "label": "status", + "type": "t_enum(Status)2240", + "offset": 26, + "slot": "8" + }, + { + "label": "disputeId", + "type": "t_uint256", + "offset": 0, + "slot": "9" + }, + { + "label": "senderFee", + "type": "t_uint256", + "offset": 0, + "slot": "10" + }, + { + "label": "receiverFee", + "type": "t_uint256", + "offset": 0, + "slot": "11" + }, + { + "label": "lastInteraction", + "type": "t_uint256", + "offset": 0, + "slot": "12" + }, + { + "label": "arbitratorExtraData", + "type": "t_bytes_storage", + "offset": 0, + "slot": "13" + }, + { + "label": "arbitrationFeeTimeout", + "type": "t_uint256", + "offset": 0, + "slot": "14" + }, + { + "label": "referrerId", + "type": "t_uint256", + "offset": 0, + "slot": "15" + }, + { + "label": "referralAmount", + "type": "t_uint256", + "offset": 0, + "slot": "16" + }, + { + "label": "totalAmount", + "type": "t_uint256", + "offset": 0, + "slot": "17" + } + ], + "numberOfBytes": "576" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" }, "t_uint256": { "label": "uint256", diff --git a/test/batch/upgrades/referral.ts b/test/batch/upgrades/referral.ts index d696a1a9..1cb3db2d 100644 --- a/test/batch/upgrades/referral.ts +++ b/test/batch/upgrades/referral.ts @@ -286,10 +286,9 @@ describe.only('TalentLayer protocol global testing', function () { expect(review.rating).to.be.equal(4) }) - it('Alice can create 1 ERC20 proposal for service 3. ', async function () { + it('Alice & Dave can create 1 ERC20 proposal each for service 3. ', async function () { // Service3(Carol): 2 proposals created ERC20, none validated - // ===> Need to validate one + 100% release + 100% reviews - + // ===> Need to validate one + 100% release // Proposal 4 await talentLayerServiceV1 .connect(alice) @@ -389,6 +388,32 @@ describe.only('TalentLayer protocol global testing', function () { }) }) }) + describe('For Service3 => Check whether a proposal can be validated after upgrade', async function () { + it("Even if Dave's proposal used ERC20 token, the validated one will be with MATIC", async function () { + const totalAmount = getTotalTransactionValue( + talentLayerEscrow, + talentLayerPlatformID, + rateAmount, + ) + // await token.connect(carol).approve(talentLayerEscrow.address, totalAmount) + const service3Data = await talentLayerService.services(3) + console.log('service3Data', service3Data.rateToken) + + // Transaction 3 + await talentLayerEscrow.connect(carol).createTransaction(3, daveTlId, metaEvidenceCid, cid, { + value: totalAmount, + }) + const transactionData = await talentLayerEscrow.connect(carol).getTransactionDetails(3) + expect(transactionData.id).to.be.equal(3) + expect(transactionData.token).to.be.equal(ethers.constants.AddressZero) + }) + it('All funds can be released & reimbursed', async function () { + await talentLayerEscrow.connect(dave).reimburse(daveTlId, 3, (rateAmount * 9) / 10) + await talentLayerEscrow.connect(carol).release(carolTlId, 3, rateAmount / 10) + const transactionData = await talentLayerEscrow.connect(dave).getTransactionDetails(3) + expect(transactionData.amount).to.be.equal(0) + }) + }) }) const getTotalTransactionValue = async ( From 05a458cff563d1bde2df79d5679327d8379a19f1 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Tue, 20 Jun 2023 19:52:13 +0200 Subject: [PATCH 86/99] Revert address update Signed-off-by: Quentin D.C --- .deployment/mumbai.json | 13 +++--- .openzeppelin/polygon-mumbai.json | 75 ------------------------------- 2 files changed, 6 insertions(+), 82 deletions(-) diff --git a/.deployment/mumbai.json b/.deployment/mumbai.json index 729b8a46..ec6951d5 100644 --- a/.deployment/mumbai.json +++ b/.deployment/mumbai.json @@ -1,9 +1,8 @@ { - "talentLayerPlatformIdAddress": "0xE95a9d7d673716e40B8aa9851592672D6D697c25", - "talentLayerIdAddress": "0x87a247A1Aed184F7BC2b4F287Fc23D82E720721b", - "talentLayerServiceAddress": "0x9B7C6FB51D2EEE39b259BDe874710642120a58ED", - "talentLayerReviewAddress": "0x815035199D281be97D092710fE659445F1EB0DC9", - "talentLayerArbitratorAddress": "0x3fBE0B906feF4507caB4e3E17DeDaBcA5b43bda1", - "talentLayerEscrowAddress": "0xC184101F1C1E4D71bd18F88FB7f36F53ec4F2De8", - "simpleERC20Address": "0x1A87740Fc249E8F917AF7D1F99bfBD4eEd6f98A1" + "talentLayerPlatformIdAddress": "0xEFD8dbC421380Ee04BAdB69216a0FD97F64CbFD4", + "talentLayerIdAddress": "0x3F87289e6Ec2D05C32d8A74CCfb30773fF549306", + "talentLayerServiceAddress": "0x27ED516dC1df64b4c1517A64aa2Bb72a434a5A6D", + "talentLayerReviewAddress": "0x050F59E1871d3B7ca97e6fb9DCE64b3818b14B18", + "talentLayerArbitratorAddress": "0x2CA01a0058cfB3cc4755a7773881ea88eCfBba7C", + "talentLayerEscrowAddress": "0x4bE920eC3e8552292B2147480111063E0dc36872" } \ No newline at end of file diff --git a/.openzeppelin/polygon-mumbai.json b/.openzeppelin/polygon-mumbai.json index 8482d372..0d8729fa 100644 --- a/.openzeppelin/polygon-mumbai.json +++ b/.openzeppelin/polygon-mumbai.json @@ -25,81 +25,6 @@ "address": "0x4bE920eC3e8552292B2147480111063E0dc36872", "txHash": "0xb2eccc32f9e60d7bbb7b0297ff37ae643a2c0bab4946c86f5ceccbda77e7d03e", "kind": "uups" - }, - { - "address": "0xe7cF60676481E7EDf4a65d873fdF1df5f35041d8", - "txHash": "0x72a093efefb6520d38bcc5b3a60c9aff0b31781f50223709082f8b2f70f9aac3", - "kind": "uups" - }, - { - "address": "0x4a1d2953Eb422C9D57c05e494D1c646359281086", - "txHash": "0xa4e22d4e49c6b80519d4eb0ac7f7994dd10cdd1c8ec30374e08c8a4efe40b171", - "kind": "uups" - }, - { - "address": "0x324b099eE546aAb9CbfA364e8473964808Ec9791", - "txHash": "0xebdaaef4b9ade450259c96e3fc98bddcbe7eb08e758edaf062cf01e0b1bdf308", - "kind": "uups" - }, - { - "address": "0x57d97B065e55Be23B69bb5Ef12AA10F03E60e666", - "txHash": "0x7fca3ea858f59b5e391f69d27d83479db2bff1f6cd09dd8f3a9ef56e97355c3a", - "kind": "uups" - }, - { - "address": "0x86D6E6e059188744f327c56d615e441c207EDAcc", - "txHash": "0xb88702f76f56e13c715f577449255e654ab173bf5f61a31aa860ebf8ed0652f6", - "kind": "uups" - }, - { - "address": "0xA4f18F9Ead22c7806312a2C5Bb13180862CbB2a4", - "txHash": "0x8d02fc775f0c76fba9fd62f44b9a66315cf8a77e8d3c045310493e4455d87696", - "kind": "uups" - }, - { - "address": "0xBd6561a6AfBC0d37F686fab22FfC07618d29b895", - "txHash": "0x9dd9fd0896cc8c949b44a0dec9de557ef5ce46606667ced12cae4ae584339cf6", - "kind": "uups" - }, - { - "address": "0x839C7b9F4c006499bcD2Ab3585F94CAC25dE47C6", - "txHash": "0x05e505c29768d3a44ee07845a9b83f0b4c86208d0b1998da1e8e451824ba2ae3", - "kind": "uups" - }, - { - "address": "0x999803a07C2769a585bDAf03Cb967F5927FB388E", - "txHash": "0xb41356e140e4e16646da63827ccb017bc82040d7cc7962bb20afcffc96781511", - "kind": "uups" - }, - { - "address": "0x684456006ec704A82f6fB5a39F671E82271aa1e9", - "txHash": "0xba3eb8a4186c673a22faa180a23d1239d2692a2a4528d5f37c070bb4336c7056", - "kind": "uups" - }, - { - "address": "0xE95a9d7d673716e40B8aa9851592672D6D697c25", - "txHash": "0xfc60f72212ed9b2e91a76fda0970e21e4a2497c4c295c00b1f562b3258de6981", - "kind": "uups" - }, - { - "address": "0x87a247A1Aed184F7BC2b4F287Fc23D82E720721b", - "txHash": "0x7c1cdf22df899c7184d4e97378145c50c4ac925a55ab78a7a35479c00d77850f", - "kind": "uups" - }, - { - "address": "0x9B7C6FB51D2EEE39b259BDe874710642120a58ED", - "txHash": "0x56386681e00f646cd517fff0136fcf78b81f4aaff5e0d86e6fd4e83240c51cd2", - "kind": "uups" - }, - { - "address": "0x815035199D281be97D092710fE659445F1EB0DC9", - "txHash": "0xa0e9da97d0b4584193a8240ea530a189b43c681ebe8e80211560a23aee6a9dac", - "kind": "uups" - }, - { - "address": "0xC184101F1C1E4D71bd18F88FB7f36F53ec4F2De8", - "txHash": "0xe24c084fbbfedb3347ce3c4e2ed0901e2e7929861d980634d7ef55263eab3e74", - "kind": "uups" } ], "impls": { From 7f949814d17fe3332fdb49a28a6929842399a3c6 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Tue, 20 Jun 2023 20:32:58 +0200 Subject: [PATCH 87/99] Finalized referral upgrade tests Signed-off-by: Quentin D.C --- test/batch/upgrades/referral.ts | 61 +++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 11 deletions(-) diff --git a/test/batch/upgrades/referral.ts b/test/batch/upgrades/referral.ts index 1cb3db2d..77afd279 100644 --- a/test/batch/upgrades/referral.ts +++ b/test/batch/upgrades/referral.ts @@ -38,7 +38,7 @@ const fakeSignature = '0xea53f5cd3f7db698f2fdd38909c58fbd41fe35b54d5b0d6acc3b05555bae1f01795b86ea1d65d8c76954fd6cefd5c59c9c57274966a071be1ee3b783a123ff961b' const alicePlatformProposalPostingFee = 0 -describe.only('TalentLayer protocol global testing', function () { +describe('TalentLayer protocol global testing', function () { let deployer: SignerWithAddress, alice: SignerWithAddress, bob: SignerWithAddress, @@ -54,11 +54,7 @@ describe.only('TalentLayer protocol global testing', function () { talentLayerArbitrator: TalentLayerArbitrator, token: SimpleERC20, platformName: string, - platformId: string, - mintFee: number - - const nonListedToken = '0x6b175474e89094c44da98b954eedeac495271d0f' - const referralAmount = 20000 + platformId: string before(async function () { // Get the Signers @@ -89,7 +85,6 @@ describe.only('TalentLayer protocol global testing', function () { // Deployer mints Platform Id for Alice platformName = 'rac00n-corp' await talentLayerPlatformID.connect(deployer).mintForAddress(platformName, alice.address) - mintFee = 100 const allowedTokenList = ['0x0000000000000000000000000000000000000000', token.address] @@ -321,7 +316,7 @@ describe.only('TalentLayer protocol global testing', function () { }, ) }) - // Service4: Nothing + // Service4(dave): Nothing // ===> Need to create proposal after service creation, validate it, release 90%, reimburse 10% and review 100% }) @@ -358,6 +353,8 @@ describe.only('TalentLayer protocol global testing', function () { await talentLayerEscrow.connect(bob).reimburse(bobTlId, 1, rateAmount / 10) const transactionData = await talentLayerEscrow.connect(alice).getTransactionDetails(1) expect(transactionData.amount).to.be.equal(0) + // @dev: Legacy transactions should have this field equal to zero + expect(transactionData.totalAmount).to.be.equal(0) }) it('Bob & Alice can both review the service', async function () { await talentLayerReview.connect(bob).mint(bobTlId, 1, cid, 5) @@ -388,7 +385,7 @@ describe.only('TalentLayer protocol global testing', function () { }) }) }) - describe('For Service3 => Check whether a proposal can be validated after upgrade', async function () { + describe('For Service3 => Check whether a proposal created before an upgrade can be validated after upgrade', async function () { it("Even if Dave's proposal used ERC20 token, the validated one will be with MATIC", async function () { const totalAmount = getTotalTransactionValue( talentLayerEscrow, @@ -396,8 +393,6 @@ describe.only('TalentLayer protocol global testing', function () { rateAmount, ) // await token.connect(carol).approve(talentLayerEscrow.address, totalAmount) - const service3Data = await talentLayerService.services(3) - console.log('service3Data', service3Data.rateToken) // Transaction 3 await talentLayerEscrow.connect(carol).createTransaction(3, daveTlId, metaEvidenceCid, cid, { @@ -414,6 +409,50 @@ describe.only('TalentLayer protocol global testing', function () { expect(transactionData.amount).to.be.equal(0) }) }) + describe('For Service4 => Check whether a proposal can be created after the upgrade for a service created before', async function () { + it("Carol can create a proposal for Dave's service & both can release & reimburse", async function () { + await talentLayerService + .connect(carol) + .createProposal( + carolTlId, + 4, + rateAmount, + 1, + cid, + proposalExpirationDate, + fakeSignature, + 0, + { + value: alicePlatformProposalPostingFee, + }, + ) + + const totalAmount = getTotalTransactionValue( + talentLayerEscrow, + talentLayerPlatformID, + rateAmount, + ) + + // Transaction 4 + await talentLayerEscrow.connect(dave).createTransaction(4, carolTlId, metaEvidenceCid, cid, { + value: totalAmount, + }) + const transactionData = await talentLayerEscrow.connect(dave).getTransactionDetails(4) + expect(transactionData.id).to.be.equal(4) + expect(transactionData.token).to.be.equal(ethers.constants.AddressZero) + expect(transactionData.totalAmount).to.be.equal(rateAmount) + expect(transactionData.sender).to.be.equal(dave.address) + expect(transactionData.receiver).to.be.equal(carol.address) + expect(transactionData.totalAmount).to.be.equal(rateAmount) + expect(transactionData.referrerId).to.be.equal(0) + }) + it('All funds can be released & reimbursed', async function () { + await talentLayerEscrow.connect(dave).release(daveTlId, 4, (rateAmount * 9) / 10) + await talentLayerEscrow.connect(carol).reimburse(carolTlId, 4, rateAmount / 10) + const transactionData = await talentLayerEscrow.connect(dave).getTransactionDetails(4) + expect(transactionData.amount).to.be.equal(0) + }) + }) }) const getTotalTransactionValue = async ( From f25d1b500944623a4a8e0c43496492926586eeb2 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Tue, 20 Jun 2023 20:33:12 +0200 Subject: [PATCH 88/99] Final check on Escrow NatSpec Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index cd3efee9..1c3bda05 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -89,8 +89,8 @@ contract TalentLayerEscrow is * @param arbitratorExtraData Extra data to set up the arbitration. * @param arbitrationFeeTimeout timeout for parties to pay the arbitration fee * @param referrerId the id of the optional referrer - * @param referralAmount the optional lump sum optional fee to be sent to the referrer - * @param totalAmount The amount of the transaction EXCLUDING FEES (will not vary) + * @param referralAmount the optional lump sum optional amount to be sent to the referrer + * @param totalAmount The amount of the transaction EXCLUDING FEES (fixed, will not vary) */ struct Transaction { uint256 id; @@ -157,7 +157,7 @@ contract TalentLayerEscrow is /** * @notice Emitted after a referrer withdraws its balance - * @param _referrerId The Platform ID to which the balance is transferred. + * @param _referrerId The TalentLayerID to which the balance is transferred. * @param _token The address of the token used for the payment. * @param _amount The amount transferred. */ @@ -404,7 +404,7 @@ contract TalentLayerEscrow is /** * @dev Only the owner of the platform ID or the owner can execute this function - * @param _token Token address ("0" for ETH) + * @param _token Token address (address(0) for ETH) * @return balance The balance of the platform or the protocol */ function getClaimableFeeBalance(address _token) external view returns (uint256 balance) { @@ -419,8 +419,7 @@ contract TalentLayerEscrow is } /** - * @dev Only the owner of the referrer ID can execute this function - * @param _token Token address ("0" for ETH) + * @param _token Token address (address(0) for ETH) * @return balance The balance of the referrer */ function getClaimableReferralBalance(address _token) external view returns (uint256 balance) { @@ -488,7 +487,7 @@ contract TalentLayerEscrow is * @param _serviceId Id of the service that the sender created and the proposal was made for. * @param _proposalId Id of the proposal that the transaction validates. * @param _metaEvidence Link to the meta-evidence. - * @param _originDataUri dataURI of the validated proposal + * @param _originDataUri dataURI of the validated proposal. */ function createTransaction( uint256 _serviceId, @@ -577,7 +576,7 @@ contract TalentLayerEscrow is /** * @notice Allows the sender to release locked-in escrow value to the intended recipient. * The amount released must not include the fees. - * @param _profileId The TalentLayer ID of the user + * @param _profileId The TalentLayer ID of the user. * @param _transactionId Id of the transaction to release escrow value for. * @param _amount Value to be released without fees. Should not be more than amount locked in. */ @@ -598,7 +597,7 @@ contract TalentLayerEscrow is /** * @notice Allows the intended receiver to return locked-in escrow value back to the sender. * The amount reimbursed must not include the fees. - * @param _profileId The TalentLayer ID of the user + * @param _profileId The TalentLayer ID of the user. * @param _transactionId Id of the transaction to reimburse escrow value for. * @param _amount Value to be reimbursed without fees. Should not be more than amount locked in. */ @@ -787,7 +786,7 @@ contract TalentLayerEscrow is * @notice Allows a referrer to claim its tokens & / or ETH balance. * @param _referrerId The ID of the referrer claiming the balance. * @param _tokenAddress The address of the Token contract (address(0) if balance in ETH). - * Emits a BalanceTransferred & a ReferralAmountClaimed events + * @dev Emits a BalanceTransferred & a ReferralAmountClaimed events */ function claimReferralBalance(uint256 _referrerId, address _tokenAddress) external whenNotPaused { address payable recipient; @@ -915,7 +914,7 @@ contract TalentLayerEscrow is // =========================== Private functions ============================== /** - * @notice Emits the events related to the creation of a transaction. + * @notice Emits the events related to the creation of a transaction * @param _senderId The TL ID of the sender * @param _receiverId The TL ID of the receiver * @param _transactionId The ID of the transaction @@ -973,6 +972,7 @@ contract TalentLayerEscrow is // If no referrerId (=0), the referralAmount will always be 0 // @dev: Legacy transactions will have a totalAmount of 0; need to check for that + // @dev: This check should be removed in a future upgrade, when all legacy transactions will be completed uint256 reimbursedReferralAmount = transaction.totalAmount != 0 ? (_amount * transaction.referralAmount) / (transaction.totalAmount) : 0; @@ -1102,7 +1102,7 @@ contract TalentLayerEscrow is * @param _amount The core escrow amount * @param _originServiceFeeRate the %fee (per ten thousands) asked by the platform for each service created on the platform * @param _originValidatedProposalFeeRate the %fee (per ten thousands) asked by the platform for each validates service on the platform - * @param _referralAmount the lump sum optional fee to be sent to the referrer, if any + * @param _referralAmount the lump sum optional amount to be sent to the referrer, if any * @return totalEscrowAmount The total amount to be paid by the buyer (including all fees + escrow) The amount to transfer */ function _calculateTotalWithFees( From f4d13f0e533327410f866840f04bcf5218af6d0b Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Tue, 20 Jun 2023 20:42:06 +0200 Subject: [PATCH 89/99] Final check on Service NatSpec Signed-off-by: Quentin D.C --- contracts/TalentLayerService.sol | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/TalentLayerService.sol b/contracts/TalentLayerService.sol index 7c0a1188..7fb880fb 100644 --- a/contracts/TalentLayerService.sol +++ b/contracts/TalentLayerService.sol @@ -47,7 +47,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param transactionId the escrow transaction ID linked to the service * @param platformId the platform ID on which the service was created * @param rateToken the token used for the service's payments, including the referral amount - * @param referralAmount the amount which the referrer will receive if a proposal is validated by un user which was referred + * @param referralAmount the amount which the referrer will receive if a proposal provided it's ID as a referrer and was validated */ struct Service { Status status; @@ -94,13 +94,13 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU // =========================== Events ============================== /** - * @notice Emitted after a new service is created with referral data + * @notice Emitted after a new service is created * @param id The service ID (incremental) * @param ownerId the talentLayerId of the buyer * @param platformId platform ID on which the Service token was minted * @param dataUri token Id to IPFS URI mapping * @param rateToken the token used for the service's payments, including the referral amount - * @param referralAmount the amount which the referrer will receive if a proposal is validated by un user which was referred + * @param referralAmount the amount which the referrer will receive if a proposal provided it's ID as a referrer and was validated */ event ServiceCreated( uint256 id, @@ -192,7 +192,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU ITalentLayerID private tlId; /** - * @notice TalentLayer Platform ID registry contract + * @notice TalentLayerPlatformId contract */ ITalentLayerPlatformID public talentLayerPlatformIdContract; @@ -316,7 +316,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @param _dataUri IPFS URI of the offchain data of the service * @param _signature optional platform signature to allow the operation * @param _rateToken token address to be used for the service's payments - * @param _referralAmount the amount which the referrer will receive if a proposal is validated by un user which was referred + * @param _referralAmount the amount which the referrer will receive if a proposal provided it's ID as a referrer and was validated */ function createService( uint256 _profileId, From 5fed2059c98833f03dc753c95e786d53d4aebf12 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 26 Jul 2023 11:31:25 +0200 Subject: [PATCH 90/99] Updated Escrow contract to modify fee calculation Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index 1c3bda05..1b8ef4f1 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -1111,12 +1111,12 @@ contract TalentLayerEscrow is uint16 _originValidatedProposalFeeRate, uint256 _referralAmount ) private view returns (uint256 totalEscrowAmount) { + uint256 totalAmount = _amount + _referralAmount; totalEscrowAmount = - _amount + - (((_amount * protocolEscrowFeeRate) + - (_amount * _originServiceFeeRate) + - (_amount * _originValidatedProposalFeeRate)) / FEE_DIVIDER) + - _referralAmount; + totalAmount + + (((totalAmount * protocolEscrowFeeRate) + + (totalAmount * _originServiceFeeRate) + + (totalAmount * _originValidatedProposalFeeRate)) / FEE_DIVIDER); } // =========================== Overrides ============================== From 118fa862f3635a2b0f709c0bc743cce907d21b0a Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Wed, 26 Jul 2023 11:31:43 +0200 Subject: [PATCH 91/99] Updated tests Signed-off-by: Quentin D.C --- test/batch/fullWorkflow.ts | 54 ++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index 698fa3a9..87d4ab7d 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -1608,16 +1608,15 @@ describe('TalentLayer protocol global testing', function () { const originServiceFeeRate = alicePlatformData.originServiceFeeRate const originValidatedProposalFeeRate = alicePlatformData.originValidatedProposalFeeRate const referralAmount = service.referralAmount - - const totalAmountWithReferral = proposal.rateAmount - .add( - proposal.rateAmount - .mul(protocolEscrowFeeRate) - .add(proposal.rateAmount.mul(originServiceFeeRate)) - .add(proposal.rateAmount.mul(originValidatedProposalFeeRate)) - .div(FEE_DIVIDER), - ) - .add(referralAmount) + const totalAmountWithoutFees = proposal.rateAmount.add(referralAmount) + + const totalAmountWithReferral = totalAmountWithoutFees.add( + totalAmountWithoutFees + .mul(protocolEscrowFeeRate) + .add(totalAmountWithoutFees.mul(originServiceFeeRate)) + .add(totalAmountWithoutFees.mul(originValidatedProposalFeeRate)) + .div(FEE_DIVIDER), + ) await token.connect(alice).approve(talentLayerEscrow.address, totalAmountWithReferral) @@ -1700,10 +1699,12 @@ describe('TalentLayer protocol global testing', function () { const reimburseReferrerAmount = reimburseAmount .mul(transactionDetails.referralAmount) .div(transactionDetails.totalAmount) - const reimburseFeesAMount = reimburseAmount + + const reimburseAmountWithReferrer = reimburseAmount.add(reimburseReferrerAmount) + const reimburseFeesAMount = reimburseAmountWithReferrer .mul(protocolEscrowFeeRate) - .add(reimburseAmount.mul(originServiceFeeRate)) - .add(reimburseAmount.mul(originValidatedProposalFeeRate)) + .add(reimburseAmountWithReferrer.mul(originServiceFeeRate)) + .add(reimburseAmountWithReferrer.mul(originValidatedProposalFeeRate)) .div(FEE_DIVIDER) const totalReimburseAmount = reimburseAmount @@ -2174,16 +2175,15 @@ describe('TalentLayer protocol global testing', function () { const originServiceFeeRate = alicePlatformData.originServiceFeeRate const originValidatedProposalFeeRate = alicePlatformData.originValidatedProposalFeeRate const referralAmount = service.referralAmount - - const totalAmountWithReferral = proposal.rateAmount - .add( - proposal.rateAmount - .mul(protocolEscrowFeeRate) - .add(proposal.rateAmount.mul(originServiceFeeRate)) - .add(proposal.rateAmount.mul(originValidatedProposalFeeRate)) - .div(FEE_DIVIDER), - ) - .add(referralAmount) + const totalAmountWithoutFees = proposal.rateAmount.add(referralAmount) + + const totalAmountWithReferral = totalAmountWithoutFees.add( + totalAmountWithoutFees + .mul(protocolEscrowFeeRate) + .add(totalAmountWithoutFees.mul(originServiceFeeRate)) + .add(totalAmountWithoutFees.mul(originValidatedProposalFeeRate)) + .div(FEE_DIVIDER), + ) // Fails if value sent is not the total amount const tx = talentLayerEscrow @@ -2271,10 +2271,12 @@ describe('TalentLayer protocol global testing', function () { const reimburseReferrerAmount = reimburseAmount .mul(transactionDetails.referralAmount) .div(transactionDetails.totalAmount) - const reimburseFeesAMount = reimburseAmount + + const reimburseAmountWithReferrer = reimburseAmount.add(reimburseReferrerAmount) + const reimburseFeesAMount = reimburseAmountWithReferrer .mul(protocolEscrowFeeRate) - .add(reimburseAmount.mul(originServiceFeeRate)) - .add(reimburseAmount.mul(originValidatedProposalFeeRate)) + .add(reimburseAmountWithReferrer.mul(originServiceFeeRate)) + .add(reimburseAmountWithReferrer.mul(originValidatedProposalFeeRate)) .div(FEE_DIVIDER) const totalReimburseAmount = reimburseAmount From 8f90926340da65031634791c218cffa1cb77160c Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Fri, 28 Jul 2023 21:56:29 +0200 Subject: [PATCH 92/99] Reverted changes in json files Signed-off-by: Quentin D.C --- .openzeppelin/polygon-mumbai.json | 3154 +++++++---------------------- 1 file changed, 769 insertions(+), 2385 deletions(-) diff --git a/.openzeppelin/polygon-mumbai.json b/.openzeppelin/polygon-mumbai.json index 0d8729fa..96dd0d0f 100644 --- a/.openzeppelin/polygon-mumbai.json +++ b/.openzeppelin/polygon-mumbai.json @@ -794,9 +794,9 @@ } } }, - "452eb25e1c135f95b329252e20212c01eb69015592373af7097bb11bb44a9ae1": { - "address": "0xb943224A83e4C3340e8b974dBE559692D9BE3e40", - "txHash": "0x7a412a32f2f50ec0f91d6e0198d78df1272da5cb1c49f0d9944b6c7d673972fe", + "c980df0f3f2d12ed5c153d563a1fbbb3da4380540f0f81a91a88015668a2090b": { + "address": "0xB60f8b4f06B66ecc75806cC5bbfc17b6eF8e56D7", + "txHash": "0xbe5bd8de2d13887a8f6109045d69507b8ab9e16cb1875656b2ca746af012603f", "layout": { "solcVersion": "0.8.17", "storage": [ @@ -806,7 +806,7 @@ "slot": "0", "type": "t_uint8", "contract": "Initializable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:62", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", "retypedFrom": "bool" }, { @@ -815,7 +815,7 @@ "slot": "0", "type": "t_bool", "contract": "Initializable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:67" + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" }, { "label": "__gap", @@ -823,183 +823,143 @@ "slot": "1", "type": "t_array(t_uint256)50_storage", "contract": "ContextUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\utils\\ContextUpgradeable.sol:36" + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" }, { - "label": "__gap", + "label": "_owner", "offset": 0, "slot": "51", - "type": "t_array(t_uint256)50_storage", - "contract": "ERC165Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\utils\\introspection\\ERC165Upgradeable.sol:41" - }, - { - "label": "_name", - "offset": 0, - "slot": "101", - "type": "t_string_storage", - "contract": "ERC721Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:25" - }, - { - "label": "_symbol", - "offset": 0, - "slot": "102", - "type": "t_string_storage", - "contract": "ERC721Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:28" + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" }, { - "label": "_owners", + "label": "__gap", "offset": 0, - "slot": "103", - "type": "t_mapping(t_uint256,t_address)", - "contract": "ERC721Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:31" + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" }, { - "label": "_balances", + "label": "_trustedForwarders", "offset": 0, - "slot": "104", - "type": "t_mapping(t_address,t_uint256)", - "contract": "ERC721Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:34" + "slot": "101", + "type": "t_mapping(t_address,t_bool)", + "contract": "ERC2771RecipientUpgradeable", + "src": "contracts/libs/ERC2771RecipientUpgradeable.sol:29" }, { - "label": "_tokenApprovals", + "label": "__gap", "offset": 0, - "slot": "105", - "type": "t_mapping(t_uint256,t_address)", - "contract": "ERC721Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:37" + "slot": "102", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:211" }, { - "label": "_operatorApprovals", + "label": "__gap", "offset": 0, - "slot": "106", - "type": "t_mapping(t_address,t_mapping(t_address,t_bool))", - "contract": "ERC721Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:40" + "slot": "152", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:107" }, { "label": "__gap", "offset": 0, - "slot": "107", - "type": "t_array(t_uint256)44_storage", - "contract": "ERC721Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:514" + "slot": "202", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC165Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" }, { "label": "_roles", "offset": 0, - "slot": "151", + "slot": "252", "type": "t_mapping(t_bytes32,t_struct(RoleData)58_storage)", "contract": "AccessControlUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\access\\AccessControlUpgradeable.sol:61" + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61" }, { "label": "__gap", "offset": 0, - "slot": "152", + "slot": "253", "type": "t_array(t_uint256)49_storage", "contract": "AccessControlUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\access\\AccessControlUpgradeable.sol:259" - }, - { - "label": "__gap", - "offset": 0, - "slot": "201", - "type": "t_array(t_uint256)50_storage", - "contract": "ERC1967UpgradeUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\ERC1967\\ERC1967UpgradeUpgradeable.sol:211" - }, - { - "label": "__gap", - "offset": 0, - "slot": "251", - "type": "t_array(t_uint256)50_storage", - "contract": "UUPSUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\UUPSUpgradeable.sol:107" - }, - { - "label": "takenNames", - "offset": 0, - "slot": "301", - "type": "t_mapping(t_string_memory_ptr,t_bool)", - "contract": "TalentLayerPlatformID", - "src": "contracts\\TalentLayerPlatformID.sol:65" + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:259" }, { - "label": "platforms", + "label": "nextServiceId", "offset": 0, "slot": "302", - "type": "t_mapping(t_uint256,t_struct(Platform)12888_storage)", - "contract": "TalentLayerPlatformID", - "src": "contracts\\TalentLayerPlatformID.sol:70" + "type": "t_uint256", + "contract": "TalentLayerService", + "src": "contracts/TalentLayerService.sol:171" }, { - "label": "validArbitrators", + "label": "tlId", "offset": 0, "slot": "303", - "type": "t_mapping(t_address,t_bool)", - "contract": "TalentLayerPlatformID", - "src": "contracts\\TalentLayerPlatformID.sol:75" + "type": "t_contract(ITalentLayerID)15000", + "contract": "TalentLayerService", + "src": "contracts/TalentLayerService.sol:176" }, { - "label": "whitelist", + "label": "talentLayerPlatformIdContract", "offset": 0, "slot": "304", - "type": "t_mapping(t_address,t_bool)", - "contract": "TalentLayerPlatformID", - "src": "contracts\\TalentLayerPlatformID.sol:80" + "type": "t_contract(ITalentLayerPlatformID)15212", + "contract": "TalentLayerService", + "src": "contracts/TalentLayerService.sol:181" }, { - "label": "internalArbitrators", + "label": "services", "offset": 0, "slot": "305", - "type": "t_mapping(t_address,t_bool)", - "contract": "TalentLayerPlatformID", - "src": "contracts\\TalentLayerPlatformID.sol:86" + "type": "t_mapping(t_uint256,t_struct(Service)13472_storage)", + "contract": "TalentLayerService", + "src": "contracts/TalentLayerService.sol:186" }, { - "label": "ids", + "label": "proposals", "offset": 0, "slot": "306", - "type": "t_mapping(t_address,t_uint256)", - "contract": "TalentLayerPlatformID", - "src": "contracts\\TalentLayerPlatformID.sol:91" + "type": "t_mapping(t_uint256,t_mapping(t_uint256,t_struct(Proposal)13488_storage))", + "contract": "TalentLayerService", + "src": "contracts/TalentLayerService.sol:191" }, { - "label": "mintFee", + "label": "serviceNonce", "offset": 0, "slot": "307", - "type": "t_uint256", - "contract": "TalentLayerPlatformID", - "src": "contracts\\TalentLayerPlatformID.sol:96" + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "TalentLayerService", + "src": "contracts/TalentLayerService.sol:196" }, { - "label": "minArbitrationFeeTimeout", + "label": "proposalNonce", "offset": 0, "slot": "308", - "type": "t_uint256", - "contract": "TalentLayerPlatformID", - "src": "contracts\\TalentLayerPlatformID.sol:106" + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "TalentLayerService", + "src": "contracts/TalentLayerService.sol:201" }, { - "label": "nextPlatformId", + "label": "allowedTokenList", "offset": 0, "slot": "309", - "type": "t_struct(Counter)3290_storage", - "contract": "TalentLayerPlatformID", - "src": "contracts\\TalentLayerPlatformID.sol:111" + "type": "t_mapping(t_address,t_struct(AllowedToken)13493_storage)", + "contract": "TalentLayerService", + "src": "contracts/TalentLayerService.sol:206" }, { - "label": "mintStatus", + "label": "minCompletionPercentage", "offset": 0, "slot": "310", - "type": "t_enum(MintStatus)12864", - "contract": "TalentLayerPlatformID", - "src": "contracts\\TalentLayerPlatformID.sol:116" + "type": "t_uint256", + "contract": "TalentLayerService", + "src": "contracts/TalentLayerService.sol:211" } ], "types": { @@ -1007,10 +967,6 @@ "label": "address", "numberOfBytes": "20" }, - "t_array(t_uint256)44_storage": { - "label": "uint256[44]", - "numberOfBytes": "1408" - }, "t_array(t_uint256)49_storage": { "label": "uint256[49]", "numberOfBytes": "1568" @@ -1027,20 +983,30 @@ "label": "bytes32", "numberOfBytes": "32" }, - "t_bytes_storage": { - "label": "bytes", - "numberOfBytes": "32" + "t_contract(ITalentLayerID)15000": { + "label": "contract ITalentLayerID", + "numberOfBytes": "20" }, - "t_contract(Arbitrator)7789": { - "label": "contract Arbitrator", + "t_contract(ITalentLayerPlatformID)15212": { + "label": "contract ITalentLayerPlatformID", "numberOfBytes": "20" }, - "t_enum(MintStatus)12864": { - "label": "enum TalentLayerPlatformID.MintStatus", + "t_enum(ProposalStatus)13458": { + "label": "enum TalentLayerService.ProposalStatus", "members": [ - "ON_PAUSE", - "ONLY_WHITELIST", - "PUBLIC" + "Pending", + "Validated" + ], + "numberOfBytes": "1" + }, + "t_enum(Status)13455": { + "label": "enum TalentLayerService.Status", + "members": [ + "Opened", + "Confirmed", + "Finished", + "Cancelled", + "Uncompleted" ], "numberOfBytes": "1" }, @@ -1048,143 +1014,159 @@ "label": "mapping(address => bool)", "numberOfBytes": "32" }, - "t_mapping(t_address,t_mapping(t_address,t_bool))": { - "label": "mapping(address => mapping(address => bool))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_uint256)": { - "label": "mapping(address => uint256)", + "t_mapping(t_address,t_struct(AllowedToken)13493_storage)": { + "label": "mapping(address => struct TalentLayerService.AllowedToken)", "numberOfBytes": "32" }, "t_mapping(t_bytes32,t_struct(RoleData)58_storage)": { "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", "numberOfBytes": "32" }, - "t_mapping(t_string_memory_ptr,t_bool)": { - "label": "mapping(string => bool)", + "t_mapping(t_uint256,t_mapping(t_uint256,t_struct(Proposal)13488_storage))": { + "label": "mapping(uint256 => mapping(uint256 => struct TalentLayerService.Proposal))", "numberOfBytes": "32" }, - "t_mapping(t_uint256,t_address)": { - "label": "mapping(uint256 => address)", + "t_mapping(t_uint256,t_struct(Proposal)13488_storage)": { + "label": "mapping(uint256 => struct TalentLayerService.Proposal)", "numberOfBytes": "32" }, - "t_mapping(t_uint256,t_struct(Platform)12888_storage)": { - "label": "mapping(uint256 => struct TalentLayerPlatformID.Platform)", + "t_mapping(t_uint256,t_struct(Service)13472_storage)": { + "label": "mapping(uint256 => struct TalentLayerService.Service)", "numberOfBytes": "32" }, - "t_string_memory_ptr": { - "label": "string", + "t_mapping(t_uint256,t_uint256)": { + "label": "mapping(uint256 => uint256)", "numberOfBytes": "32" }, "t_string_storage": { "label": "string", "numberOfBytes": "32" }, - "t_struct(Counter)3290_storage": { - "label": "struct CountersUpgradeable.Counter", + "t_struct(AllowedToken)13493_storage": { + "label": "struct TalentLayerService.AllowedToken", "members": [ { - "label": "_value", - "type": "t_uint256", + "label": "isWhitelisted", + "type": "t_bool", "offset": 0, "slot": "0" + }, + { + "label": "minimumTransactionAmount", + "type": "t_uint256", + "offset": 0, + "slot": "1" } ], - "numberOfBytes": "32" + "numberOfBytes": "64" }, - "t_struct(Platform)12888_storage": { - "label": "struct TalentLayerPlatformID.Platform", + "t_struct(Proposal)13488_storage": { + "label": "struct TalentLayerService.Proposal", "members": [ { - "label": "id", - "type": "t_uint256", + "label": "status", + "type": "t_enum(ProposalStatus)13458", "offset": 0, "slot": "0" }, { - "label": "name", - "type": "t_string_storage", + "label": "ownerId", + "type": "t_uint256", "offset": 0, "slot": "1" }, { - "label": "dataUri", - "type": "t_string_storage", + "label": "rateToken", + "type": "t_address", "offset": 0, "slot": "2" }, { - "label": "originServiceFeeRate", - "type": "t_uint16", + "label": "rateAmount", + "type": "t_uint256", "offset": 0, "slot": "3" }, { - "label": "originValidatedProposalFeeRate", - "type": "t_uint16", - "offset": 2, - "slot": "3" - }, - { - "label": "servicePostingFee", + "label": "platformId", "type": "t_uint256", "offset": 0, "slot": "4" }, { - "label": "proposalPostingFee", - "type": "t_uint256", + "label": "dataUri", + "type": "t_string_storage", "offset": 0, "slot": "5" }, { - "label": "arbitrator", - "type": "t_contract(Arbitrator)7789", + "label": "expirationDate", + "type": "t_uint256", "offset": 0, "slot": "6" - }, + } + ], + "numberOfBytes": "224" + }, + "t_struct(RoleData)58_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ { - "label": "arbitratorExtraData", - "type": "t_bytes_storage", + "label": "members", + "type": "t_mapping(t_address,t_bool)", "offset": 0, - "slot": "7" + "slot": "0" }, { - "label": "arbitrationFeeTimeout", - "type": "t_uint256", - "offset": 0, - "slot": "8" - }, - { - "label": "signer", - "type": "t_address", + "label": "adminRole", + "type": "t_bytes32", "offset": 0, - "slot": "9" + "slot": "1" } ], - "numberOfBytes": "320" + "numberOfBytes": "64" }, - "t_struct(RoleData)58_storage": { - "label": "struct AccessControlUpgradeable.RoleData", + "t_struct(Service)13472_storage": { + "label": "struct TalentLayerService.Service", "members": [ { - "label": "members", - "type": "t_mapping(t_address,t_bool)", + "label": "status", + "type": "t_enum(Status)13455", "offset": 0, "slot": "0" }, { - "label": "adminRole", - "type": "t_bytes32", + "label": "ownerId", + "type": "t_uint256", "offset": 0, "slot": "1" + }, + { + "label": "acceptedProposalId", + "type": "t_uint256", + "offset": 0, + "slot": "2" + }, + { + "label": "dataUri", + "type": "t_string_storage", + "offset": 0, + "slot": "3" + }, + { + "label": "transactionId", + "type": "t_uint256", + "offset": 0, + "slot": "4" + }, + { + "label": "platformId", + "type": "t_uint256", + "offset": 0, + "slot": "5" } ], - "numberOfBytes": "64" - }, - "t_uint16": { - "label": "uint16", - "numberOfBytes": "2" + "numberOfBytes": "192" }, "t_uint256": { "label": "uint256", @@ -1197,9 +1179,9 @@ } } }, - "f9e7916a1c316964ab24794f96ac3ee47b57790f1fb37e7a459ebb7c82af0d2e": { - "address": "0x35BA74f9D1de2E1401798ae5c71678FEd4b25380", - "txHash": "0x8f6e51fe0b9b012092985b3ed726fb4e6581b62f52762fc9208a35ca3f3d26a8", + "88ab1cdc37255e380eb6a7ab9e7ed0ef4fb8be10681fc961f9547c5db21335ec": { + "address": "0x3d18c9C94faD1444F9c2bD052D5c7D6D2C52e420", + "txHash": "0x5207e2000f745e2a4d10d4d2d327c24bdb04bf359fea1b8302348698537dc8a6", "layout": { "solcVersion": "0.8.17", "storage": [ @@ -1209,7 +1191,7 @@ "slot": "0", "type": "t_uint8", "contract": "Initializable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:62", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", "retypedFrom": "bool" }, { @@ -1218,7 +1200,7 @@ "slot": "0", "type": "t_bool", "contract": "Initializable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:67" + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" }, { "label": "__gap", @@ -1226,7 +1208,7 @@ "slot": "1", "type": "t_array(t_uint256)50_storage", "contract": "ContextUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\utils\\ContextUpgradeable.sol:36" + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" }, { "label": "_owner", @@ -1234,7 +1216,7 @@ "slot": "51", "type": "t_address", "contract": "OwnableUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:22" + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" }, { "label": "__gap", @@ -1242,7 +1224,7 @@ "slot": "52", "type": "t_array(t_uint256)49_storage", "contract": "OwnableUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:94" + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" }, { "label": "_trustedForwarders", @@ -1250,7 +1232,7 @@ "slot": "101", "type": "t_mapping(t_address,t_bool)", "contract": "ERC2771RecipientUpgradeable", - "src": "contracts\\libs\\ERC2771RecipientUpgradeable.sol:29" + "src": "contracts/libs/ERC2771RecipientUpgradeable.sol:29" }, { "label": "__gap", @@ -1258,7 +1240,7 @@ "slot": "102", "type": "t_array(t_uint256)50_storage", "contract": "ERC165Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\utils\\introspection\\ERC165Upgradeable.sol:41" + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" }, { "label": "_name", @@ -1266,7 +1248,7 @@ "slot": "152", "type": "t_string_storage", "contract": "ERC721Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:25" + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:25" }, { "label": "_symbol", @@ -1274,7 +1256,7 @@ "slot": "153", "type": "t_string_storage", "contract": "ERC721Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:28" + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:28" }, { "label": "_owners", @@ -1282,7 +1264,7 @@ "slot": "154", "type": "t_mapping(t_uint256,t_address)", "contract": "ERC721Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:31" + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:31" }, { "label": "_balances", @@ -1290,7 +1272,7 @@ "slot": "155", "type": "t_mapping(t_address,t_uint256)", "contract": "ERC721Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:34" + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:34" }, { "label": "_tokenApprovals", @@ -1298,7 +1280,7 @@ "slot": "156", "type": "t_mapping(t_uint256,t_address)", "contract": "ERC721Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:37" + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:37" }, { "label": "_operatorApprovals", @@ -1306,7 +1288,7 @@ "slot": "157", "type": "t_mapping(t_address,t_mapping(t_address,t_bool))", "contract": "ERC721Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:40" + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:40" }, { "label": "__gap", @@ -1314,7 +1296,7 @@ "slot": "158", "type": "t_array(t_uint256)44_storage", "contract": "ERC721Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:514" + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:514" }, { "label": "__gap", @@ -1322,7 +1304,7 @@ "slot": "202", "type": "t_array(t_uint256)50_storage", "contract": "ERC1967UpgradeUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\ERC1967\\ERC1967UpgradeUpgradeable.sol:211" + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:211" }, { "label": "__gap", @@ -1330,103 +1312,55 @@ "slot": "252", "type": "t_array(t_uint256)50_storage", "contract": "UUPSUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\UUPSUpgradeable.sol:107" + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:107" }, { - "label": "talentLayerPlatformIdContract", + "label": "nextReviewId", "offset": 0, "slot": "302", - "type": "t_contract(ITalentLayerPlatformID)16292", - "contract": "TalentLayerID", - "src": "contracts\\TalentLayerID.sol:70" + "type": "t_struct(Counter)3290_storage", + "contract": "TalentLayerReview", + "src": "contracts/TalentLayerReview.sol:47" }, { - "label": "takenHandles", + "label": "reviews", "offset": 0, "slot": "303", - "type": "t_mapping(t_string_memory_ptr,t_bool)", - "contract": "TalentLayerID", - "src": "contracts\\TalentLayerID.sol:75" + "type": "t_mapping(t_uint256,t_struct(Review)12991_storage)", + "contract": "TalentLayerReview", + "src": "contracts/TalentLayerReview.sol:52" }, { - "label": "profiles", + "label": "hasBuyerBeenReviewed", "offset": 0, "slot": "304", - "type": "t_mapping(t_uint256,t_struct(Profile)11510_storage)", - "contract": "TalentLayerID", - "src": "contracts\\TalentLayerID.sol:80" + "type": "t_mapping(t_uint256,t_bool)", + "contract": "TalentLayerReview", + "src": "contracts/TalentLayerReview.sol:57" }, { - "label": "ids", + "label": "hasSellerBeenReviewed", "offset": 0, "slot": "305", - "type": "t_mapping(t_address,t_uint256)", - "contract": "TalentLayerID", - "src": "contracts\\TalentLayerID.sol:85" + "type": "t_mapping(t_uint256,t_bool)", + "contract": "TalentLayerReview", + "src": "contracts/TalentLayerReview.sol:62" }, { - "label": "mintFee", + "label": "tlId", "offset": 0, "slot": "306", - "type": "t_uint256", - "contract": "TalentLayerID", - "src": "contracts\\TalentLayerID.sol:90" + "type": "t_contract(ITalentLayerID)15000", + "contract": "TalentLayerReview", + "src": "contracts/TalentLayerReview.sol:67" }, { - "label": "nextProfileId", + "label": "talentLayerService", "offset": 0, "slot": "307", - "type": "t_struct(Counter)3290_storage", - "contract": "TalentLayerID", - "src": "contracts\\TalentLayerID.sol:95" - }, - { - "label": "delegates", - "offset": 0, - "slot": "308", - "type": "t_mapping(t_uint256,t_mapping(t_address,t_bool))", - "contract": "TalentLayerID", - "src": "contracts\\TalentLayerID.sol:100" - }, - { - "label": "whitelistMerkleRoot", - "offset": 0, - "slot": "309", - "type": "t_bytes32", - "contract": "TalentLayerID", - "src": "contracts\\TalentLayerID.sol:105" - }, - { - "label": "mintStatus", - "offset": 0, - "slot": "310", - "type": "t_enum(MintStatus)11501", - "contract": "TalentLayerID", - "src": "contracts\\TalentLayerID.sol:110" - }, - { - "label": "shortHandlesMaxPrice", - "offset": 0, - "slot": "311", - "type": "t_uint256", - "contract": "TalentLayerID", - "src": "contracts\\TalentLayerID.sol:115" - }, - { - "label": "hasActivity", - "offset": 0, - "slot": "312", - "type": "t_mapping(t_uint256,t_bool)", - "contract": "TalentLayerID", - "src": "contracts\\TalentLayerID.sol:120" - }, - { - "label": "isServiceContract", - "offset": 0, - "slot": "313", - "type": "t_mapping(t_address,t_bool)", - "contract": "TalentLayerID", - "src": "contracts\\TalentLayerID.sol:125" + "type": "t_contract(ITalentLayerService)15385", + "contract": "TalentLayerReview", + "src": "contracts/TalentLayerReview.sol:72" } ], "types": { @@ -1450,22 +1384,13 @@ "label": "bool", "numberOfBytes": "1" }, - "t_bytes32": { - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_contract(ITalentLayerPlatformID)16292": { - "label": "contract ITalentLayerPlatformID", + "t_contract(ITalentLayerID)15000": { + "label": "contract ITalentLayerID", "numberOfBytes": "20" }, - "t_enum(MintStatus)11501": { - "label": "enum TalentLayerID.MintStatus", - "members": [ - "ON_PAUSE", - "ONLY_WHITELIST", - "PUBLIC" - ], - "numberOfBytes": "1" + "t_contract(ITalentLayerService)15385": { + "label": "contract ITalentLayerService", + "numberOfBytes": "20" }, "t_mapping(t_address,t_bool)": { "label": "mapping(address => bool)", @@ -1479,10 +1404,6 @@ "label": "mapping(address => uint256)", "numberOfBytes": "32" }, - "t_mapping(t_string_memory_ptr,t_bool)": { - "label": "mapping(string => bool)", - "numberOfBytes": "32" - }, "t_mapping(t_uint256,t_address)": { "label": "mapping(uint256 => address)", "numberOfBytes": "32" @@ -1491,16 +1412,8 @@ "label": "mapping(uint256 => bool)", "numberOfBytes": "32" }, - "t_mapping(t_uint256,t_mapping(t_address,t_bool))": { - "label": "mapping(uint256 => mapping(address => bool))", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_struct(Profile)11510_storage)": { - "label": "mapping(uint256 => struct TalentLayerID.Profile)", - "numberOfBytes": "32" - }, - "t_string_memory_ptr": { - "label": "string", + "t_mapping(t_uint256,t_struct(Review)12991_storage)": { + "label": "mapping(uint256 => struct TalentLayerReview.Review)", "numberOfBytes": "32" }, "t_string_storage": { @@ -1519,8 +1432,8 @@ ], "numberOfBytes": "32" }, - "t_struct(Profile)11510_storage": { - "label": "struct TalentLayerID.Profile", + "t_struct(Review)12991_storage": { + "label": "struct TalentLayerReview.Review", "members": [ { "label": "id", @@ -1529,25 +1442,31 @@ "slot": "0" }, { - "label": "handle", - "type": "t_string_storage", + "label": "ownerId", + "type": "t_uint256", "offset": 0, "slot": "1" }, { - "label": "platformId", - "type": "t_uint256", + "label": "dataUri", + "type": "t_string_storage", "offset": 0, "slot": "2" }, { - "label": "dataUri", - "type": "t_string_storage", + "label": "serviceId", + "type": "t_uint256", "offset": 0, "slot": "3" + }, + { + "label": "rating", + "type": "t_uint256", + "offset": 0, + "slot": "4" } ], - "numberOfBytes": "128" + "numberOfBytes": "160" }, "t_uint256": { "label": "uint256", @@ -1560,9 +1479,9 @@ } } }, - "c980df0f3f2d12ed5c153d563a1fbbb3da4380540f0f81a91a88015668a2090b": { - "address": "0xA685EEBC106CC8FAcaFca58236F2ece3Ee9f1a29", - "txHash": "0x41074e203dff9f4a7b89523db272d10f09efeed401ac741a85beb6a257070ad7", + "09aac2d047d78f74214c535af98f3c37c37ef8536acce8b970ff6e54e333c9c1": { + "address": "0x7d5e41423179901E507D168967A4edE0dD088c8a", + "txHash": "0x25f75b2b14e9166f6b1798f5b06770be1637ff56249acd65bc71d57711e944df", "layout": { "solcVersion": "0.8.17", "storage": [ @@ -1572,7 +1491,7 @@ "slot": "0", "type": "t_uint8", "contract": "Initializable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:62", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", "retypedFrom": "bool" }, { @@ -1581,7 +1500,7 @@ "slot": "0", "type": "t_bool", "contract": "Initializable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:67" + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" }, { "label": "__gap", @@ -1589,7 +1508,7 @@ "slot": "1", "type": "t_array(t_uint256)50_storage", "contract": "ContextUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\utils\\ContextUpgradeable.sol:36" + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" }, { "label": "_owner", @@ -1597,7 +1516,7 @@ "slot": "51", "type": "t_address", "contract": "OwnableUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:22" + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" }, { "label": "__gap", @@ -1605,7 +1524,7 @@ "slot": "52", "type": "t_array(t_uint256)49_storage", "contract": "OwnableUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:94" + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" }, { "label": "_trustedForwarders", @@ -1613,119 +1532,111 @@ "slot": "101", "type": "t_mapping(t_address,t_bool)", "contract": "ERC2771RecipientUpgradeable", - "src": "contracts\\libs\\ERC2771RecipientUpgradeable.sol:29" + "src": "contracts/libs/ERC2771RecipientUpgradeable.sol:29" }, { - "label": "__gap", + "label": "_paused", "offset": 0, "slot": "102", - "type": "t_array(t_uint256)50_storage", - "contract": "ERC1967UpgradeUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\ERC1967\\ERC1967UpgradeUpgradeable.sol:211" + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "103", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:116" }, { "label": "__gap", "offset": 0, "slot": "152", "type": "t_array(t_uint256)50_storage", - "contract": "UUPSUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\UUPSUpgradeable.sol:107" + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:211" }, { "label": "__gap", "offset": 0, "slot": "202", "type": "t_array(t_uint256)50_storage", - "contract": "ERC165Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\utils\\introspection\\ERC165Upgradeable.sol:41" + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:107" }, { - "label": "_roles", + "label": "transactions", "offset": 0, "slot": "252", - "type": "t_mapping(t_bytes32,t_struct(RoleData)58_storage)", - "contract": "AccessControlUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\access\\AccessControlUpgradeable.sol:61" + "type": "t_mapping(t_uint256,t_struct(Transaction)8196_storage)", + "contract": "TalentLayerEscrow", + "src": "contracts/TalentLayerEscrow.sol:252" }, { - "label": "__gap", + "label": "platformIdToTokenToBalance", "offset": 0, "slot": "253", - "type": "t_array(t_uint256)49_storage", - "contract": "AccessControlUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\access\\AccessControlUpgradeable.sol:259" + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", + "contract": "TalentLayerEscrow", + "src": "contracts/TalentLayerEscrow.sol:261" }, { - "label": "nextServiceId", + "label": "talentLayerServiceContract", "offset": 0, - "slot": "302", - "type": "t_uint256", - "contract": "TalentLayerServiceV1", - "src": "contracts\\archive\\TalentLayerServiceV1.sol:171" + "slot": "254", + "type": "t_contract(ITalentLayerService)15385", + "contract": "TalentLayerEscrow", + "src": "contracts/TalentLayerEscrow.sol:266" }, { - "label": "tlId", + "label": "talentLayerIdContract", "offset": 0, - "slot": "303", - "type": "t_contract(ITalentLayerID)19906", - "contract": "TalentLayerServiceV1", - "src": "contracts\\archive\\TalentLayerServiceV1.sol:176" + "slot": "255", + "type": "t_contract(ITalentLayerID)15000", + "contract": "TalentLayerEscrow", + "src": "contracts/TalentLayerEscrow.sol:271" }, { "label": "talentLayerPlatformIdContract", "offset": 0, - "slot": "304", - "type": "t_contract(ITalentLayerPlatformID)20118", - "contract": "TalentLayerServiceV1", - "src": "contracts\\archive\\TalentLayerServiceV1.sol:181" + "slot": "256", + "type": "t_contract(ITalentLayerPlatformID)15212", + "contract": "TalentLayerEscrow", + "src": "contracts/TalentLayerEscrow.sol:276" }, { - "label": "services", + "label": "protocolWallet", "offset": 0, - "slot": "305", - "type": "t_mapping(t_uint256,t_struct(Service)18364_storage)", - "contract": "TalentLayerServiceV1", - "src": "contracts\\archive\\TalentLayerServiceV1.sol:186" + "slot": "257", + "type": "t_address_payable", + "contract": "TalentLayerEscrow", + "src": "contracts/TalentLayerEscrow.sol:281" }, { - "label": "proposals", - "offset": 0, - "slot": "306", - "type": "t_mapping(t_uint256,t_mapping(t_uint256,t_struct(Proposal)18380_storage))", - "contract": "TalentLayerServiceV1", - "src": "contracts\\archive\\TalentLayerServiceV1.sol:191" - }, - { - "label": "serviceNonce", - "offset": 0, - "slot": "307", - "type": "t_mapping(t_uint256,t_uint256)", - "contract": "TalentLayerServiceV1", - "src": "contracts\\archive\\TalentLayerServiceV1.sol:196" + "label": "protocolEscrowFeeRate", + "offset": 20, + "slot": "257", + "type": "t_uint16", + "contract": "TalentLayerEscrow", + "src": "contracts/TalentLayerEscrow.sol:286" }, { - "label": "proposalNonce", + "label": "disputeIDtoTransactionID", "offset": 0, - "slot": "308", + "slot": "258", "type": "t_mapping(t_uint256,t_uint256)", - "contract": "TalentLayerServiceV1", - "src": "contracts\\archive\\TalentLayerServiceV1.sol:201" - }, - { - "label": "allowedTokenList", - "offset": 0, - "slot": "309", - "type": "t_mapping(t_address,t_struct(AllowedToken)18385_storage)", - "contract": "TalentLayerServiceV1", - "src": "contracts\\archive\\TalentLayerServiceV1.sol:206" + "contract": "TalentLayerEscrow", + "src": "contracts/TalentLayerEscrow.sol:316" }, { - "label": "minCompletionPercentage", + "label": "nextTransactionId", "offset": 0, - "slot": "310", - "type": "t_uint256", - "contract": "TalentLayerServiceV1", - "src": "contracts\\archive\\TalentLayerServiceV1.sol:211" + "slot": "259", + "type": "t_struct(Counter)3290_storage", + "contract": "TalentLayerEscrow", + "src": "contracts/TalentLayerEscrow.sol:321" } ], "types": { @@ -1733,6 +1644,10 @@ "label": "address", "numberOfBytes": "20" }, + "t_address_payable": { + "label": "address payable", + "numberOfBytes": "20" + }, "t_array(t_uint256)49_storage": { "label": "uint256[49]", "numberOfBytes": "1568" @@ -1745,34 +1660,34 @@ "label": "bool", "numberOfBytes": "1" }, - "t_bytes32": { - "label": "bytes32", + "t_bytes_storage": { + "label": "bytes", "numberOfBytes": "32" }, - "t_contract(ITalentLayerID)19906": { + "t_contract(Arbitrator)7789": { + "label": "contract Arbitrator", + "numberOfBytes": "20" + }, + "t_contract(ITalentLayerID)15000": { "label": "contract ITalentLayerID", "numberOfBytes": "20" }, - "t_contract(ITalentLayerPlatformID)20118": { + "t_contract(ITalentLayerPlatformID)15212": { "label": "contract ITalentLayerPlatformID", "numberOfBytes": "20" }, - "t_enum(ProposalStatus)18350": { - "label": "enum TalentLayerServiceV1.ProposalStatus", - "members": [ - "Pending", - "Validated" - ], - "numberOfBytes": "1" + "t_contract(ITalentLayerService)15385": { + "label": "contract ITalentLayerService", + "numberOfBytes": "20" }, - "t_enum(Status)18347": { - "label": "enum TalentLayerServiceV1.Status", + "t_enum(Status)8155": { + "label": "enum TalentLayerEscrow.Status", "members": [ - "Opened", - "Confirmed", - "Finished", - "Cancelled", - "Uncompleted" + "NoDispute", + "WaitingSender", + "WaitingReceiver", + "DisputeCreated", + "Resolved" ], "numberOfBytes": "1" }, @@ -1780,159 +1695,157 @@ "label": "mapping(address => bool)", "numberOfBytes": "32" }, - "t_mapping(t_address,t_struct(AllowedToken)18385_storage)": { - "label": "mapping(address => struct TalentLayerServiceV1.AllowedToken)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes32,t_struct(RoleData)58_storage)": { - "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_mapping(t_uint256,t_struct(Proposal)18380_storage))": { - "label": "mapping(uint256 => mapping(uint256 => struct TalentLayerServiceV1.Proposal))", + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", "numberOfBytes": "32" }, - "t_mapping(t_uint256,t_struct(Proposal)18380_storage)": { - "label": "mapping(uint256 => struct TalentLayerServiceV1.Proposal)", + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "label": "mapping(uint256 => mapping(address => uint256))", "numberOfBytes": "32" }, - "t_mapping(t_uint256,t_struct(Service)18364_storage)": { - "label": "mapping(uint256 => struct TalentLayerServiceV1.Service)", + "t_mapping(t_uint256,t_struct(Transaction)8196_storage)": { + "label": "mapping(uint256 => struct TalentLayerEscrow.Transaction)", "numberOfBytes": "32" }, "t_mapping(t_uint256,t_uint256)": { "label": "mapping(uint256 => uint256)", "numberOfBytes": "32" }, - "t_string_storage": { - "label": "string", - "numberOfBytes": "32" - }, - "t_struct(AllowedToken)18385_storage": { - "label": "struct TalentLayerServiceV1.AllowedToken", + "t_struct(Counter)3290_storage": { + "label": "struct CountersUpgradeable.Counter", "members": [ { - "label": "isWhitelisted", - "type": "t_bool", - "offset": 0, - "slot": "0" - }, - { - "label": "minimumTransactionAmount", + "label": "_value", "type": "t_uint256", "offset": 0, - "slot": "1" + "slot": "0" } ], - "numberOfBytes": "64" + "numberOfBytes": "32" }, - "t_struct(Proposal)18380_storage": { - "label": "struct TalentLayerServiceV1.Proposal", + "t_struct(Transaction)8196_storage": { + "label": "struct TalentLayerEscrow.Transaction", "members": [ { - "label": "status", - "type": "t_enum(ProposalStatus)18350", + "label": "id", + "type": "t_uint256", "offset": 0, "slot": "0" }, { - "label": "ownerId", - "type": "t_uint256", + "label": "sender", + "type": "t_address", "offset": 0, "slot": "1" }, { - "label": "rateToken", + "label": "receiver", "type": "t_address", "offset": 0, "slot": "2" }, { - "label": "rateAmount", - "type": "t_uint256", + "label": "token", + "type": "t_address", "offset": 0, "slot": "3" }, { - "label": "platformId", + "label": "amount", "type": "t_uint256", "offset": 0, "slot": "4" }, { - "label": "dataUri", - "type": "t_string_storage", + "label": "releasedAmount", + "type": "t_uint256", "offset": 0, "slot": "5" }, { - "label": "expirationDate", + "label": "serviceId", "type": "t_uint256", "offset": 0, "slot": "6" - } - ], - "numberOfBytes": "224" - }, - "t_struct(RoleData)58_storage": { - "label": "struct AccessControlUpgradeable.RoleData", - "members": [ + }, { - "label": "members", - "type": "t_mapping(t_address,t_bool)", + "label": "proposalId", + "type": "t_uint256", "offset": 0, - "slot": "0" + "slot": "7" }, { - "label": "adminRole", - "type": "t_bytes32", + "label": "protocolEscrowFeeRate", + "type": "t_uint16", "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_struct(Service)18364_storage": { - "label": "struct TalentLayerServiceV1.Service", - "members": [ + "slot": "8" + }, + { + "label": "originServiceFeeRate", + "type": "t_uint16", + "offset": 2, + "slot": "8" + }, + { + "label": "originValidatedProposalFeeRate", + "type": "t_uint16", + "offset": 4, + "slot": "8" + }, + { + "label": "arbitrator", + "type": "t_contract(Arbitrator)7789", + "offset": 6, + "slot": "8" + }, { "label": "status", - "type": "t_enum(Status)18347", - "offset": 0, - "slot": "0" + "type": "t_enum(Status)8155", + "offset": 26, + "slot": "8" }, { - "label": "ownerId", + "label": "disputeId", "type": "t_uint256", "offset": 0, - "slot": "1" + "slot": "9" }, { - "label": "acceptedProposalId", + "label": "senderFee", "type": "t_uint256", "offset": 0, - "slot": "2" + "slot": "10" }, { - "label": "dataUri", - "type": "t_string_storage", + "label": "receiverFee", + "type": "t_uint256", "offset": 0, - "slot": "3" + "slot": "11" }, { - "label": "transactionId", + "label": "lastInteraction", "type": "t_uint256", "offset": 0, - "slot": "4" + "slot": "12" }, { - "label": "platformId", + "label": "arbitratorExtraData", + "type": "t_bytes_storage", + "offset": 0, + "slot": "13" + }, + { + "label": "arbitrationFeeTimeout", "type": "t_uint256", "offset": 0, - "slot": "5" + "slot": "14" } ], - "numberOfBytes": "192" + "numberOfBytes": "480" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" }, "t_uint256": { "label": "uint256", @@ -1945,9 +1858,9 @@ } } }, - "88ab1cdc37255e380eb6a7ab9e7ed0ef4fb8be10681fc961f9547c5db21335ec": { - "address": "0xF8d44F8cA3a601ea67B0f46D202E9a11C2768092", - "txHash": "0x66c44f1580ffd16727bf7004fece1e2740d1f3411afa4825682878c221907492", + "452eb25e1c135f95b329252e20212c01eb69015592373af7097bb11bb44a9ae1": { + "address": "0xd726887633a87B4eC52633123681177e77bD02E1", + "txHash": "0xd90fb37bcdf965f0e7d897d12c206e8d68c30ea945d3b2a0bc022e0ed1dcf1c5", "layout": { "solcVersion": "0.8.17", "storage": [ @@ -1957,7 +1870,7 @@ "slot": "0", "type": "t_uint8", "contract": "Initializable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:62", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", "retypedFrom": "bool" }, { @@ -1966,7 +1879,7 @@ "slot": "0", "type": "t_bool", "contract": "Initializable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:67" + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" }, { "label": "__gap", @@ -1974,159 +1887,183 @@ "slot": "1", "type": "t_array(t_uint256)50_storage", "contract": "ContextUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\utils\\ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:94" - }, - { - "label": "_trustedForwarders", - "offset": 0, - "slot": "101", - "type": "t_mapping(t_address,t_bool)", - "contract": "ERC2771RecipientUpgradeable", - "src": "contracts\\libs\\ERC2771RecipientUpgradeable.sol:29" + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" }, { "label": "__gap", "offset": 0, - "slot": "102", + "slot": "51", "type": "t_array(t_uint256)50_storage", "contract": "ERC165Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\utils\\introspection\\ERC165Upgradeable.sol:41" + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" }, { "label": "_name", "offset": 0, - "slot": "152", + "slot": "101", "type": "t_string_storage", "contract": "ERC721Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:25" + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:25" }, { "label": "_symbol", "offset": 0, - "slot": "153", + "slot": "102", "type": "t_string_storage", "contract": "ERC721Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:28" + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:28" }, { "label": "_owners", "offset": 0, - "slot": "154", + "slot": "103", "type": "t_mapping(t_uint256,t_address)", "contract": "ERC721Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:31" + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:31" }, { "label": "_balances", "offset": 0, - "slot": "155", + "slot": "104", "type": "t_mapping(t_address,t_uint256)", "contract": "ERC721Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:34" + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:34" }, { "label": "_tokenApprovals", "offset": 0, - "slot": "156", + "slot": "105", "type": "t_mapping(t_uint256,t_address)", "contract": "ERC721Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:37" + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:37" }, { "label": "_operatorApprovals", "offset": 0, - "slot": "157", + "slot": "106", "type": "t_mapping(t_address,t_mapping(t_address,t_bool))", "contract": "ERC721Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:40" + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:40" }, { "label": "__gap", "offset": 0, - "slot": "158", + "slot": "107", "type": "t_array(t_uint256)44_storage", "contract": "ERC721Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:514" + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:514" }, { - "label": "__gap", + "label": "_roles", "offset": 0, - "slot": "202", - "type": "t_array(t_uint256)50_storage", - "contract": "ERC1967UpgradeUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\ERC1967\\ERC1967UpgradeUpgradeable.sol:211" + "slot": "151", + "type": "t_mapping(t_bytes32,t_struct(RoleData)58_storage)", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61" }, { "label": "__gap", "offset": 0, - "slot": "252", - "type": "t_array(t_uint256)50_storage", - "contract": "UUPSUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\UUPSUpgradeable.sol:107" - }, - { - "label": "nextReviewId", + "slot": "152", + "type": "t_array(t_uint256)49_storage", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:259" + }, + { + "label": "__gap", + "offset": 0, + "slot": "201", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:211" + }, + { + "label": "__gap", + "offset": 0, + "slot": "251", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:107" + }, + { + "label": "takenNames", + "offset": 0, + "slot": "301", + "type": "t_mapping(t_string_memory_ptr,t_bool)", + "contract": "TalentLayerPlatformID", + "src": "contracts/TalentLayerPlatformID.sol:65" + }, + { + "label": "platforms", "offset": 0, "slot": "302", - "type": "t_struct(Counter)3290_storage", - "contract": "TalentLayerReview", - "src": "contracts\\TalentLayerReview.sol:47" + "type": "t_mapping(t_uint256,t_struct(Platform)5970_storage)", + "contract": "TalentLayerPlatformID", + "src": "contracts/TalentLayerPlatformID.sol:70" }, { - "label": "reviews", + "label": "validArbitrators", "offset": 0, "slot": "303", - "type": "t_mapping(t_uint256,t_struct(Review)14071_storage)", - "contract": "TalentLayerReview", - "src": "contracts\\TalentLayerReview.sol:52" + "type": "t_mapping(t_address,t_bool)", + "contract": "TalentLayerPlatformID", + "src": "contracts/TalentLayerPlatformID.sol:75" }, { - "label": "hasBuyerBeenReviewed", + "label": "whitelist", "offset": 0, "slot": "304", - "type": "t_mapping(t_uint256,t_bool)", - "contract": "TalentLayerReview", - "src": "contracts\\TalentLayerReview.sol:57" + "type": "t_mapping(t_address,t_bool)", + "contract": "TalentLayerPlatformID", + "src": "contracts/TalentLayerPlatformID.sol:80" }, { - "label": "hasSellerBeenReviewed", + "label": "internalArbitrators", "offset": 0, "slot": "305", - "type": "t_mapping(t_uint256,t_bool)", - "contract": "TalentLayerReview", - "src": "contracts\\TalentLayerReview.sol:62" + "type": "t_mapping(t_address,t_bool)", + "contract": "TalentLayerPlatformID", + "src": "contracts/TalentLayerPlatformID.sol:86" }, { - "label": "tlId", + "label": "ids", "offset": 0, "slot": "306", - "type": "t_contract(ITalentLayerID)16080", - "contract": "TalentLayerReview", - "src": "contracts\\TalentLayerReview.sol:67" + "type": "t_mapping(t_address,t_uint256)", + "contract": "TalentLayerPlatformID", + "src": "contracts/TalentLayerPlatformID.sol:91" }, { - "label": "talentLayerService", + "label": "mintFee", "offset": 0, "slot": "307", - "type": "t_contract(ITalentLayerService)16465", - "contract": "TalentLayerReview", - "src": "contracts\\TalentLayerReview.sol:72" + "type": "t_uint256", + "contract": "TalentLayerPlatformID", + "src": "contracts/TalentLayerPlatformID.sol:96" + }, + { + "label": "minArbitrationFeeTimeout", + "offset": 0, + "slot": "308", + "type": "t_uint256", + "contract": "TalentLayerPlatformID", + "src": "contracts/TalentLayerPlatformID.sol:106" + }, + { + "label": "nextPlatformId", + "offset": 0, + "slot": "309", + "type": "t_struct(Counter)2768_storage", + "contract": "TalentLayerPlatformID", + "src": "contracts/TalentLayerPlatformID.sol:111" + }, + { + "label": "mintStatus", + "offset": 0, + "slot": "310", + "type": "t_enum(MintStatus)5946", + "contract": "TalentLayerPlatformID", + "src": "contracts/TalentLayerPlatformID.sol:116" } ], "types": { @@ -2150,14 +2087,27 @@ "label": "bool", "numberOfBytes": "1" }, - "t_contract(ITalentLayerID)16080": { - "label": "contract ITalentLayerID", - "numberOfBytes": "20" + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" }, - "t_contract(ITalentLayerService)16465": { - "label": "contract ITalentLayerService", + "t_bytes_storage": { + "label": "bytes", + "numberOfBytes": "32" + }, + "t_contract(Arbitrator)4644": { + "label": "contract Arbitrator", "numberOfBytes": "20" }, + "t_enum(MintStatus)5946": { + "label": "enum TalentLayerPlatformID.MintStatus", + "members": [ + "ON_PAUSE", + "ONLY_WHITELIST", + "PUBLIC" + ], + "numberOfBytes": "1" + }, "t_mapping(t_address,t_bool)": { "label": "mapping(address => bool)", "numberOfBytes": "32" @@ -2170,23 +2120,31 @@ "label": "mapping(address => uint256)", "numberOfBytes": "32" }, + "t_mapping(t_bytes32,t_struct(RoleData)58_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32" + }, + "t_mapping(t_string_memory_ptr,t_bool)": { + "label": "mapping(string => bool)", + "numberOfBytes": "32" + }, "t_mapping(t_uint256,t_address)": { "label": "mapping(uint256 => address)", "numberOfBytes": "32" }, - "t_mapping(t_uint256,t_bool)": { - "label": "mapping(uint256 => bool)", + "t_mapping(t_uint256,t_struct(Platform)5970_storage)": { + "label": "mapping(uint256 => struct TalentLayerPlatformID.Platform)", "numberOfBytes": "32" }, - "t_mapping(t_uint256,t_struct(Review)14071_storage)": { - "label": "mapping(uint256 => struct TalentLayerReview.Review)", + "t_string_memory_ptr": { + "label": "string", "numberOfBytes": "32" }, "t_string_storage": { "label": "string", "numberOfBytes": "32" }, - "t_struct(Counter)3290_storage": { + "t_struct(Counter)2768_storage": { "label": "struct CountersUpgradeable.Counter", "members": [ { @@ -2198,8 +2156,8 @@ ], "numberOfBytes": "32" }, - "t_struct(Review)14071_storage": { - "label": "struct TalentLayerReview.Review", + "t_struct(Platform)5970_storage": { + "label": "struct TalentLayerPlatformID.Platform", "members": [ { "label": "id", @@ -2208,8 +2166,8 @@ "slot": "0" }, { - "label": "ownerId", - "type": "t_uint256", + "label": "name", + "type": "t_string_storage", "offset": 0, "slot": "1" }, @@ -2220,19 +2178,77 @@ "slot": "2" }, { - "label": "serviceId", - "type": "t_uint256", + "label": "originServiceFeeRate", + "type": "t_uint16", "offset": 0, "slot": "3" }, { - "label": "rating", + "label": "originValidatedProposalFeeRate", + "type": "t_uint16", + "offset": 2, + "slot": "3" + }, + { + "label": "servicePostingFee", "type": "t_uint256", "offset": 0, "slot": "4" + }, + { + "label": "proposalPostingFee", + "type": "t_uint256", + "offset": 0, + "slot": "5" + }, + { + "label": "arbitrator", + "type": "t_contract(Arbitrator)4644", + "offset": 0, + "slot": "6" + }, + { + "label": "arbitratorExtraData", + "type": "t_bytes_storage", + "offset": 0, + "slot": "7" + }, + { + "label": "arbitrationFeeTimeout", + "type": "t_uint256", + "offset": 0, + "slot": "8" + }, + { + "label": "signer", + "type": "t_address", + "offset": 0, + "slot": "9" } ], - "numberOfBytes": "160" + "numberOfBytes": "320" + }, + "t_struct(RoleData)58_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)", + "offset": 0, + "slot": "0" + }, + { + "label": "adminRole", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" }, "t_uint256": { "label": "uint256", @@ -2245,9 +2261,9 @@ } } }, - "09aac2d047d78f74214c535af98f3c37c37ef8536acce8b970ff6e54e333c9c1": { - "address": "0x05E4b5bA3c4E5e79e391CC11836751AaBA3e11D4", - "txHash": "0x5aad64c0c338ee115bd6bc17856fd8a3bf1d40ab715d0b04ca1af8aea0c1e25c", + "f9e7916a1c316964ab24794f96ac3ee47b57790f1fb37e7a459ebb7c82af0d2e": { + "address": "0x10f5FA91077E8F0Ce4791F998bFE7233216F7E76", + "txHash": "0x7446df365bae78c03532ab0e66f0b2943fddfb5bc45115fce95e90b5d72cc58b", "layout": { "solcVersion": "0.8.17", "storage": [ @@ -2257,7 +2273,7 @@ "slot": "0", "type": "t_uint8", "contract": "Initializable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:62", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", "retypedFrom": "bool" }, { @@ -2266,7 +2282,7 @@ "slot": "0", "type": "t_bool", "contract": "Initializable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:67" + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" }, { "label": "__gap", @@ -2274,7 +2290,7 @@ "slot": "1", "type": "t_array(t_uint256)50_storage", "contract": "ContextUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\utils\\ContextUpgradeable.sol:36" + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" }, { "label": "_owner", @@ -2282,7 +2298,7 @@ "slot": "51", "type": "t_address", "contract": "OwnableUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:22" + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" }, { "label": "__gap", @@ -2290,7 +2306,7 @@ "slot": "52", "type": "t_array(t_uint256)49_storage", "contract": "OwnableUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:94" + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" }, { "label": "_trustedForwarders", @@ -2298,1709 +2314,183 @@ "slot": "101", "type": "t_mapping(t_address,t_bool)", "contract": "ERC2771RecipientUpgradeable", - "src": "contracts\\libs\\ERC2771RecipientUpgradeable.sol:29" + "src": "contracts/libs/ERC2771RecipientUpgradeable.sol:29" }, { - "label": "_paused", + "label": "__gap", "offset": 0, "slot": "102", - "type": "t_bool", - "contract": "PausableUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\security\\PausableUpgradeable.sol:29" + "type": "t_array(t_uint256)50_storage", + "contract": "ERC165Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" }, { - "label": "__gap", + "label": "_name", "offset": 0, - "slot": "103", - "type": "t_array(t_uint256)49_storage", - "contract": "PausableUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\security\\PausableUpgradeable.sol:116" + "slot": "152", + "type": "t_string_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:25" }, { - "label": "__gap", + "label": "_symbol", "offset": 0, - "slot": "152", - "type": "t_array(t_uint256)50_storage", - "contract": "ERC1967UpgradeUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\ERC1967\\ERC1967UpgradeUpgradeable.sol:211" + "slot": "153", + "type": "t_string_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:28" }, { - "label": "__gap", + "label": "_owners", "offset": 0, - "slot": "202", - "type": "t_array(t_uint256)50_storage", - "contract": "UUPSUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\UUPSUpgradeable.sol:107" + "slot": "154", + "type": "t_mapping(t_uint256,t_address)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:31" }, { - "label": "transactions", + "label": "_balances", "offset": 0, - "slot": "252", - "type": "t_mapping(t_uint256,t_struct(Transaction)2281_storage)", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:252" + "slot": "155", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:34" }, { - "label": "platformIdToTokenToBalance", + "label": "_tokenApprovals", "offset": 0, - "slot": "253", - "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:261" + "slot": "156", + "type": "t_mapping(t_uint256,t_address)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:37" }, { - "label": "talentLayerServiceContract", + "label": "_operatorApprovals", "offset": 0, - "slot": "254", - "type": "t_contract(ITalentLayerService)4997", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:266" - }, - { - "label": "talentLayerIdContract", - "offset": 0, - "slot": "255", - "type": "t_contract(ITalentLayerID)4648", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:271" - }, - { - "label": "talentLayerPlatformIdContract", - "offset": 0, - "slot": "256", - "type": "t_contract(ITalentLayerPlatformID)4860", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:276" - }, - { - "label": "protocolWallet", - "offset": 0, - "slot": "257", - "type": "t_address_payable", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:281" - }, - { - "label": "protocolEscrowFeeRate", - "offset": 20, - "slot": "257", - "type": "t_uint16", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:286" - }, - { - "label": "disputeIDtoTransactionID", - "offset": 0, - "slot": "258", - "type": "t_mapping(t_uint256,t_uint256)", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:316" - }, - { - "label": "nextTransactionId", - "offset": 0, - "slot": "259", - "type": "t_struct(Counter)1819_storage", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:321" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_address_payable": { - "label": "address payable", - "numberOfBytes": "20" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes_storage": { - "label": "bytes", - "numberOfBytes": "32" - }, - "t_contract(Arbitrator)2187": { - "label": "contract Arbitrator", - "numberOfBytes": "20" - }, - "t_contract(ITalentLayerID)4648": { - "label": "contract ITalentLayerID", - "numberOfBytes": "20" - }, - "t_contract(ITalentLayerPlatformID)4860": { - "label": "contract ITalentLayerPlatformID", - "numberOfBytes": "20" - }, - "t_contract(ITalentLayerService)4997": { - "label": "contract ITalentLayerService", - "numberOfBytes": "20" - }, - "t_enum(Status)2240": { - "label": "enum TalentLayerEscrow.Status", - "members": [ - "NoDispute", - "WaitingSender", - "WaitingReceiver", - "DisputeCreated", - "Resolved" - ], - "numberOfBytes": "1" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_uint256)": { - "label": "mapping(address => uint256)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { - "label": "mapping(uint256 => mapping(address => uint256))", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_struct(Transaction)2281_storage)": { - "label": "mapping(uint256 => struct TalentLayerEscrow.Transaction)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_uint256)": { - "label": "mapping(uint256 => uint256)", - "numberOfBytes": "32" - }, - "t_struct(Counter)1819_storage": { - "label": "struct CountersUpgradeable.Counter", - "members": [ - { - "label": "_value", - "type": "t_uint256", - "offset": 0, - "slot": "0" - } - ], - "numberOfBytes": "32" - }, - "t_struct(Transaction)2281_storage": { - "label": "struct TalentLayerEscrow.Transaction", - "members": [ - { - "label": "id", - "type": "t_uint256", - "offset": 0, - "slot": "0" - }, - { - "label": "sender", - "type": "t_address", - "offset": 0, - "slot": "1" - }, - { - "label": "receiver", - "type": "t_address", - "offset": 0, - "slot": "2" - }, - { - "label": "token", - "type": "t_address", - "offset": 0, - "slot": "3" - }, - { - "label": "amount", - "type": "t_uint256", - "offset": 0, - "slot": "4" - }, - { - "label": "releasedAmount", - "type": "t_uint256", - "offset": 0, - "slot": "5" - }, - { - "label": "serviceId", - "type": "t_uint256", - "offset": 0, - "slot": "6" - }, - { - "label": "proposalId", - "type": "t_uint256", - "offset": 0, - "slot": "7" - }, - { - "label": "protocolEscrowFeeRate", - "type": "t_uint16", - "offset": 0, - "slot": "8" - }, - { - "label": "originServiceFeeRate", - "type": "t_uint16", - "offset": 2, - "slot": "8" - }, - { - "label": "originValidatedProposalFeeRate", - "type": "t_uint16", - "offset": 4, - "slot": "8" - }, - { - "label": "arbitrator", - "type": "t_contract(Arbitrator)2187", - "offset": 6, - "slot": "8" - }, - { - "label": "status", - "type": "t_enum(Status)2240", - "offset": 26, - "slot": "8" - }, - { - "label": "disputeId", - "type": "t_uint256", - "offset": 0, - "slot": "9" - }, - { - "label": "senderFee", - "type": "t_uint256", - "offset": 0, - "slot": "10" - }, - { - "label": "receiverFee", - "type": "t_uint256", - "offset": 0, - "slot": "11" - }, - { - "label": "lastInteraction", - "type": "t_uint256", - "offset": 0, - "slot": "12" - }, - { - "label": "arbitratorExtraData", - "type": "t_bytes_storage", - "offset": 0, - "slot": "13" - }, - { - "label": "arbitrationFeeTimeout", - "type": "t_uint256", - "offset": 0, - "slot": "14" - } - ], - "numberOfBytes": "480" - }, - "t_uint16": { - "label": "uint16", - "numberOfBytes": "2" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "5b077d0944a30c4d3208cf540374f4ebf661e5ef8fae32acd57c36364fe3c7ea": { - "address": "0xd3b709d2E6923BbfDC83e990a5b0c41e4aD1e3fA", - "txHash": "0x066fe906af4ae05df1a058fbaea43c83c4a1fee1c0f05ca36d5b0189847e5deb", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:62", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:67" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\utils\\ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:94" - }, - { - "label": "_trustedForwarders", - "offset": 0, - "slot": "101", - "type": "t_mapping(t_address,t_bool)", - "contract": "ERC2771RecipientUpgradeable", - "src": "contracts\\libs\\ERC2771RecipientUpgradeable.sol:29" - }, - { - "label": "__gap", - "offset": 0, - "slot": "102", - "type": "t_array(t_uint256)50_storage", - "contract": "ERC1967UpgradeUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\ERC1967\\ERC1967UpgradeUpgradeable.sol:211" - }, - { - "label": "__gap", - "offset": 0, - "slot": "152", - "type": "t_array(t_uint256)50_storage", - "contract": "UUPSUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\UUPSUpgradeable.sol:107" - }, - { - "label": "__gap", - "offset": 0, - "slot": "202", - "type": "t_array(t_uint256)50_storage", - "contract": "ERC165Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\utils\\introspection\\ERC165Upgradeable.sol:41" - }, - { - "label": "_roles", - "offset": 0, - "slot": "252", - "type": "t_mapping(t_bytes32,t_struct(RoleData)58_storage)", - "contract": "AccessControlUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\access\\AccessControlUpgradeable.sol:61" - }, - { - "label": "__gap", - "offset": 0, - "slot": "253", - "type": "t_array(t_uint256)49_storage", - "contract": "AccessControlUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\access\\AccessControlUpgradeable.sol:259" - }, - { - "label": "nextServiceId", - "offset": 0, - "slot": "302", - "type": "t_uint256", - "contract": "TalentLayerService", - "src": "contracts\\TalentLayerService.sol:187" - }, - { - "label": "tlId", - "offset": 0, - "slot": "303", - "type": "t_contract(ITalentLayerID)9584", - "contract": "TalentLayerService", - "src": "contracts\\TalentLayerService.sol:192" - }, - { - "label": "talentLayerPlatformIdContract", - "offset": 0, - "slot": "304", - "type": "t_contract(ITalentLayerPlatformID)9796", - "contract": "TalentLayerService", - "src": "contracts\\TalentLayerService.sol:197" - }, - { - "label": "services", - "offset": 0, - "slot": "305", - "type": "t_mapping(t_uint256,t_struct(Service)8116_storage)", - "contract": "TalentLayerService", - "src": "contracts\\TalentLayerService.sol:202" - }, - { - "label": "proposals", - "offset": 0, - "slot": "306", - "type": "t_mapping(t_uint256,t_mapping(t_uint256,t_struct(Proposal)8134_storage))", - "contract": "TalentLayerService", - "src": "contracts\\TalentLayerService.sol:207" - }, - { - "label": "serviceNonce", - "offset": 0, - "slot": "307", - "type": "t_mapping(t_uint256,t_uint256)", - "contract": "TalentLayerService", - "src": "contracts\\TalentLayerService.sol:212" - }, - { - "label": "proposalNonce", - "offset": 0, - "slot": "308", - "type": "t_mapping(t_uint256,t_uint256)", - "contract": "TalentLayerService", - "src": "contracts\\TalentLayerService.sol:217" - }, - { - "label": "allowedTokenList", - "offset": 0, - "slot": "309", - "type": "t_mapping(t_address,t_struct(AllowedToken)8139_storage)", - "contract": "TalentLayerService", - "src": "contracts\\TalentLayerService.sol:222" - }, - { - "label": "minCompletionPercentage", - "offset": 0, - "slot": "310", - "type": "t_uint256", - "contract": "TalentLayerService", - "src": "contracts\\TalentLayerService.sol:227" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_contract(ITalentLayerID)9584": { - "label": "contract ITalentLayerID", - "numberOfBytes": "20" - }, - "t_contract(ITalentLayerPlatformID)9796": { - "label": "contract ITalentLayerPlatformID", - "numberOfBytes": "20" - }, - "t_enum(ProposalStatus)8098": { - "label": "enum TalentLayerService.ProposalStatus", - "members": [ - "Pending", - "Validated" - ], - "numberOfBytes": "1" - }, - "t_enum(Status)8095": { - "label": "enum TalentLayerService.Status", - "members": [ - "Opened", - "Confirmed", - "Finished", - "Cancelled", - "Uncompleted" - ], - "numberOfBytes": "1" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_struct(AllowedToken)8139_storage)": { - "label": "mapping(address => struct TalentLayerService.AllowedToken)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes32,t_struct(RoleData)58_storage)": { - "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_mapping(t_uint256,t_struct(Proposal)8134_storage))": { - "label": "mapping(uint256 => mapping(uint256 => struct TalentLayerService.Proposal))", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_struct(Proposal)8134_storage)": { - "label": "mapping(uint256 => struct TalentLayerService.Proposal)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_struct(Service)8116_storage)": { - "label": "mapping(uint256 => struct TalentLayerService.Service)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_uint256)": { - "label": "mapping(uint256 => uint256)", - "numberOfBytes": "32" - }, - "t_string_storage": { - "label": "string", - "numberOfBytes": "32" - }, - "t_struct(AllowedToken)8139_storage": { - "label": "struct TalentLayerService.AllowedToken", - "members": [ - { - "label": "isWhitelisted", - "type": "t_bool", - "offset": 0, - "slot": "0" - }, - { - "label": "minimumTransactionAmount", - "type": "t_uint256", - "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_struct(Proposal)8134_storage": { - "label": "struct TalentLayerService.Proposal", - "members": [ - { - "label": "status", - "type": "t_enum(ProposalStatus)8098", - "offset": 0, - "slot": "0" - }, - { - "label": "ownerId", - "type": "t_uint256", - "offset": 0, - "slot": "1" - }, - { - "label": "rateToken", - "type": "t_address", - "offset": 0, - "slot": "2" - }, - { - "label": "rateAmount", - "type": "t_uint256", - "offset": 0, - "slot": "3" - }, - { - "label": "platformId", - "type": "t_uint256", - "offset": 0, - "slot": "4" - }, - { - "label": "dataUri", - "type": "t_string_storage", - "offset": 0, - "slot": "5" - }, - { - "label": "expirationDate", - "type": "t_uint256", - "offset": 0, - "slot": "6" - }, - { - "label": "referrerId", - "type": "t_uint256", - "offset": 0, - "slot": "7" - } - ], - "numberOfBytes": "256" - }, - "t_struct(RoleData)58_storage": { - "label": "struct AccessControlUpgradeable.RoleData", - "members": [ - { - "label": "members", - "type": "t_mapping(t_address,t_bool)", - "offset": 0, - "slot": "0" - }, - { - "label": "adminRole", - "type": "t_bytes32", - "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_struct(Service)8116_storage": { - "label": "struct TalentLayerService.Service", - "members": [ - { - "label": "status", - "type": "t_enum(Status)8095", - "offset": 0, - "slot": "0" - }, - { - "label": "ownerId", - "type": "t_uint256", - "offset": 0, - "slot": "1" - }, - { - "label": "acceptedProposalId", - "type": "t_uint256", - "offset": 0, - "slot": "2" - }, - { - "label": "dataUri", - "type": "t_string_storage", - "offset": 0, - "slot": "3" - }, - { - "label": "transactionId", - "type": "t_uint256", - "offset": 0, - "slot": "4" - }, - { - "label": "platformId", - "type": "t_uint256", - "offset": 0, - "slot": "5" - }, - { - "label": "rateToken", - "type": "t_address", - "offset": 0, - "slot": "6" - }, - { - "label": "referralAmount", - "type": "t_uint256", - "offset": 0, - "slot": "7" - } - ], - "numberOfBytes": "256" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "a67d6aa882378162466d32952b5a0b9cbf10b9f0703e2e848749a07767f34ba2": { - "address": "0x1060a19A5Cee808ab120616ef2399983cB27A1A3", - "txHash": "0x893a5a32457797c1340e2d9d63ade6fa85c4ff19111047d73db9b95e629817a0", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:62", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:67" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\utils\\ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:94" - }, - { - "label": "_trustedForwarders", - "offset": 0, - "slot": "101", - "type": "t_mapping(t_address,t_bool)", - "contract": "ERC2771RecipientUpgradeable", - "src": "contracts\\libs\\ERC2771RecipientUpgradeable.sol:29" - }, - { - "label": "_paused", - "offset": 0, - "slot": "102", - "type": "t_bool", - "contract": "PausableUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\security\\PausableUpgradeable.sol:29" - }, - { - "label": "__gap", - "offset": 0, - "slot": "103", - "type": "t_array(t_uint256)49_storage", - "contract": "PausableUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\security\\PausableUpgradeable.sol:116" - }, - { - "label": "__gap", - "offset": 0, - "slot": "152", - "type": "t_array(t_uint256)50_storage", - "contract": "ERC1967UpgradeUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\ERC1967\\ERC1967UpgradeUpgradeable.sol:211" - }, - { - "label": "__gap", - "offset": 0, - "slot": "202", - "type": "t_array(t_uint256)50_storage", - "contract": "UUPSUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\UUPSUpgradeable.sol:107" - }, - { - "label": "transactions", - "offset": 0, - "slot": "252", - "type": "t_mapping(t_uint256,t_struct(Transaction)2287_storage)", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:280" - }, - { - "label": "platformIdToTokenToBalance", - "offset": 0, - "slot": "253", - "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:289" - }, - { - "label": "talentLayerServiceContract", - "offset": 0, - "slot": "254", - "type": "t_contract(ITalentLayerService)5225", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:294" - }, - { - "label": "talentLayerIdContract", - "offset": 0, - "slot": "255", - "type": "t_contract(ITalentLayerID)4855", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:299" - }, - { - "label": "talentLayerPlatformIdContract", - "offset": 0, - "slot": "256", - "type": "t_contract(ITalentLayerPlatformID)5067", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:304" - }, - { - "label": "protocolWallet", - "offset": 0, - "slot": "257", - "type": "t_address_payable", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:309" - }, - { - "label": "protocolEscrowFeeRate", - "offset": 20, - "slot": "257", - "type": "t_uint16", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:314" - }, - { - "label": "disputeIDtoTransactionID", - "offset": 0, - "slot": "258", - "type": "t_mapping(t_uint256,t_uint256)", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:344" - }, - { - "label": "nextTransactionId", - "offset": 0, - "slot": "259", - "type": "t_struct(Counter)1819_storage", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:349" - }, - { - "label": "referrerIdToTokenToBalance", - "offset": 0, - "slot": "260", - "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:357" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_address_payable": { - "label": "address payable", - "numberOfBytes": "20" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes_storage": { - "label": "bytes", - "numberOfBytes": "32" - }, - "t_contract(Arbitrator)2187": { - "label": "contract Arbitrator", - "numberOfBytes": "20" - }, - "t_contract(ITalentLayerID)4855": { - "label": "contract ITalentLayerID", - "numberOfBytes": "20" - }, - "t_contract(ITalentLayerPlatformID)5067": { - "label": "contract ITalentLayerPlatformID", - "numberOfBytes": "20" - }, - "t_contract(ITalentLayerService)5225": { - "label": "contract ITalentLayerService", - "numberOfBytes": "20" - }, - "t_enum(Status)2240": { - "label": "enum TalentLayerEscrow.Status", - "members": [ - "NoDispute", - "WaitingSender", - "WaitingReceiver", - "DisputeCreated", - "Resolved" - ], - "numberOfBytes": "1" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_uint256)": { - "label": "mapping(address => uint256)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { - "label": "mapping(uint256 => mapping(address => uint256))", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_struct(Transaction)2287_storage)": { - "label": "mapping(uint256 => struct TalentLayerEscrow.Transaction)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_uint256)": { - "label": "mapping(uint256 => uint256)", - "numberOfBytes": "32" - }, - "t_struct(Counter)1819_storage": { - "label": "struct CountersUpgradeable.Counter", - "members": [ - { - "label": "_value", - "type": "t_uint256", - "offset": 0, - "slot": "0" - } - ], - "numberOfBytes": "32" - }, - "t_struct(Transaction)2287_storage": { - "label": "struct TalentLayerEscrow.Transaction", - "members": [ - { - "label": "id", - "type": "t_uint256", - "offset": 0, - "slot": "0" - }, - { - "label": "sender", - "type": "t_address", - "offset": 0, - "slot": "1" - }, - { - "label": "receiver", - "type": "t_address", - "offset": 0, - "slot": "2" - }, - { - "label": "token", - "type": "t_address", - "offset": 0, - "slot": "3" - }, - { - "label": "amount", - "type": "t_uint256", - "offset": 0, - "slot": "4" - }, - { - "label": "releasedAmount", - "type": "t_uint256", - "offset": 0, - "slot": "5" - }, - { - "label": "serviceId", - "type": "t_uint256", - "offset": 0, - "slot": "6" - }, - { - "label": "proposalId", - "type": "t_uint256", - "offset": 0, - "slot": "7" - }, - { - "label": "protocolEscrowFeeRate", - "type": "t_uint16", - "offset": 0, - "slot": "8" - }, - { - "label": "originServiceFeeRate", - "type": "t_uint16", - "offset": 2, - "slot": "8" - }, - { - "label": "originValidatedProposalFeeRate", - "type": "t_uint16", - "offset": 4, - "slot": "8" - }, - { - "label": "arbitrator", - "type": "t_contract(Arbitrator)2187", - "offset": 6, - "slot": "8" - }, - { - "label": "status", - "type": "t_enum(Status)2240", - "offset": 26, - "slot": "8" - }, - { - "label": "disputeId", - "type": "t_uint256", - "offset": 0, - "slot": "9" - }, - { - "label": "senderFee", - "type": "t_uint256", - "offset": 0, - "slot": "10" - }, - { - "label": "receiverFee", - "type": "t_uint256", - "offset": 0, - "slot": "11" - }, - { - "label": "lastInteraction", - "type": "t_uint256", - "offset": 0, - "slot": "12" - }, - { - "label": "arbitratorExtraData", - "type": "t_bytes_storage", - "offset": 0, - "slot": "13" - }, - { - "label": "arbitrationFeeTimeout", - "type": "t_uint256", - "offset": 0, - "slot": "14" - }, - { - "label": "referrerId", - "type": "t_uint256", - "offset": 0, - "slot": "15" - }, - { - "label": "referralAmount", - "type": "t_uint256", - "offset": 0, - "slot": "16" - }, - { - "label": "totalAmount", - "type": "t_uint256", - "offset": 0, - "slot": "17" - } - ], - "numberOfBytes": "576" - }, - "t_uint16": { - "label": "uint16", - "numberOfBytes": "2" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "f294cc7eef142927d49f0c558eb78063d4cb38921116d44b1f3f437e0ce75a94": { - "address": "0x4e644D65cFa49C4F9431659369AD3a7809E065aa", - "txHash": "0xb4fc739de1532e08bd656895967aea3e52439c0320413fdc04b925d3b6dc1c27", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:62", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:67" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\utils\\ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:94" - }, - { - "label": "_trustedForwarders", - "offset": 0, - "slot": "101", - "type": "t_mapping(t_address,t_bool)", - "contract": "ERC2771RecipientUpgradeable", - "src": "contracts\\libs\\ERC2771RecipientUpgradeable.sol:29" - }, - { - "label": "__gap", - "offset": 0, - "slot": "102", - "type": "t_array(t_uint256)50_storage", - "contract": "ERC1967UpgradeUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\ERC1967\\ERC1967UpgradeUpgradeable.sol:211" - }, - { - "label": "__gap", - "offset": 0, - "slot": "152", - "type": "t_array(t_uint256)50_storage", - "contract": "UUPSUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\UUPSUpgradeable.sol:107" - }, - { - "label": "__gap", - "offset": 0, - "slot": "202", - "type": "t_array(t_uint256)50_storage", - "contract": "ERC165Upgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\utils\\introspection\\ERC165Upgradeable.sol:41" - }, - { - "label": "_roles", - "offset": 0, - "slot": "252", - "type": "t_mapping(t_bytes32,t_struct(RoleData)58_storage)", - "contract": "AccessControlUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\access\\AccessControlUpgradeable.sol:61" - }, - { - "label": "__gap", - "offset": 0, - "slot": "253", - "type": "t_array(t_uint256)49_storage", - "contract": "AccessControlUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\access\\AccessControlUpgradeable.sol:259" - }, - { - "label": "nextServiceId", - "offset": 0, - "slot": "302", - "type": "t_uint256", - "contract": "TalentLayerService", - "src": "contracts\\TalentLayerService.sol:187" - }, - { - "label": "tlId", - "offset": 0, - "slot": "303", - "type": "t_contract(ITalentLayerID)4885", - "contract": "TalentLayerService", - "src": "contracts\\TalentLayerService.sol:192" - }, - { - "label": "talentLayerPlatformIdContract", - "offset": 0, - "slot": "304", - "type": "t_contract(ITalentLayerPlatformID)5097", - "contract": "TalentLayerService", - "src": "contracts\\TalentLayerService.sol:197" - }, - { - "label": "services", - "offset": 0, - "slot": "305", - "type": "t_mapping(t_uint256,t_struct(Service)3417_storage)", - "contract": "TalentLayerService", - "src": "contracts\\TalentLayerService.sol:202" - }, - { - "label": "proposals", - "offset": 0, - "slot": "306", - "type": "t_mapping(t_uint256,t_mapping(t_uint256,t_struct(Proposal)3435_storage))", - "contract": "TalentLayerService", - "src": "contracts\\TalentLayerService.sol:207" - }, - { - "label": "serviceNonce", - "offset": 0, - "slot": "307", - "type": "t_mapping(t_uint256,t_uint256)", - "contract": "TalentLayerService", - "src": "contracts\\TalentLayerService.sol:212" - }, - { - "label": "proposalNonce", - "offset": 0, - "slot": "308", - "type": "t_mapping(t_uint256,t_uint256)", - "contract": "TalentLayerService", - "src": "contracts\\TalentLayerService.sol:217" - }, - { - "label": "allowedTokenList", - "offset": 0, - "slot": "309", - "type": "t_mapping(t_address,t_struct(AllowedToken)3440_storage)", - "contract": "TalentLayerService", - "src": "contracts\\TalentLayerService.sol:222" - }, - { - "label": "minCompletionPercentage", - "offset": 0, - "slot": "310", - "type": "t_uint256", - "contract": "TalentLayerService", - "src": "contracts\\TalentLayerService.sol:227" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_contract(ITalentLayerID)4885": { - "label": "contract ITalentLayerID", - "numberOfBytes": "20" - }, - "t_contract(ITalentLayerPlatformID)5097": { - "label": "contract ITalentLayerPlatformID", - "numberOfBytes": "20" - }, - "t_enum(ProposalStatus)3399": { - "label": "enum TalentLayerService.ProposalStatus", - "members": [ - "Pending", - "Validated" - ], - "numberOfBytes": "1" - }, - "t_enum(Status)3396": { - "label": "enum TalentLayerService.Status", - "members": [ - "Opened", - "Confirmed", - "Finished", - "Cancelled", - "Uncompleted" - ], - "numberOfBytes": "1" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_struct(AllowedToken)3440_storage)": { - "label": "mapping(address => struct TalentLayerService.AllowedToken)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes32,t_struct(RoleData)58_storage)": { - "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_mapping(t_uint256,t_struct(Proposal)3435_storage))": { - "label": "mapping(uint256 => mapping(uint256 => struct TalentLayerService.Proposal))", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_struct(Proposal)3435_storage)": { - "label": "mapping(uint256 => struct TalentLayerService.Proposal)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_struct(Service)3417_storage)": { - "label": "mapping(uint256 => struct TalentLayerService.Service)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_uint256)": { - "label": "mapping(uint256 => uint256)", - "numberOfBytes": "32" - }, - "t_string_storage": { - "label": "string", - "numberOfBytes": "32" - }, - "t_struct(AllowedToken)3440_storage": { - "label": "struct TalentLayerService.AllowedToken", - "members": [ - { - "label": "isWhitelisted", - "type": "t_bool", - "offset": 0, - "slot": "0" - }, - { - "label": "minimumTransactionAmount", - "type": "t_uint256", - "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_struct(Proposal)3435_storage": { - "label": "struct TalentLayerService.Proposal", - "members": [ - { - "label": "status", - "type": "t_enum(ProposalStatus)3399", - "offset": 0, - "slot": "0" - }, - { - "label": "ownerId", - "type": "t_uint256", - "offset": 0, - "slot": "1" - }, - { - "label": "rateToken", - "type": "t_address", - "offset": 0, - "slot": "2" - }, - { - "label": "rateAmount", - "type": "t_uint256", - "offset": 0, - "slot": "3" - }, - { - "label": "platformId", - "type": "t_uint256", - "offset": 0, - "slot": "4" - }, - { - "label": "dataUri", - "type": "t_string_storage", - "offset": 0, - "slot": "5" - }, - { - "label": "expirationDate", - "type": "t_uint256", - "offset": 0, - "slot": "6" - }, - { - "label": "referrerId", - "type": "t_uint256", - "offset": 0, - "slot": "7" - } - ], - "numberOfBytes": "256" - }, - "t_struct(RoleData)58_storage": { - "label": "struct AccessControlUpgradeable.RoleData", - "members": [ - { - "label": "members", - "type": "t_mapping(t_address,t_bool)", - "offset": 0, - "slot": "0" - }, - { - "label": "adminRole", - "type": "t_bytes32", - "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_struct(Service)3417_storage": { - "label": "struct TalentLayerService.Service", - "members": [ - { - "label": "status", - "type": "t_enum(Status)3396", - "offset": 0, - "slot": "0" - }, - { - "label": "ownerId", - "type": "t_uint256", - "offset": 0, - "slot": "1" - }, - { - "label": "acceptedProposalId", - "type": "t_uint256", - "offset": 0, - "slot": "2" - }, - { - "label": "dataUri", - "type": "t_string_storage", - "offset": 0, - "slot": "3" - }, - { - "label": "transactionId", - "type": "t_uint256", - "offset": 0, - "slot": "4" - }, - { - "label": "platformId", - "type": "t_uint256", - "offset": 0, - "slot": "5" - }, - { - "label": "rateToken", - "type": "t_address", - "offset": 0, - "slot": "6" - }, - { - "label": "referralAmount", - "type": "t_uint256", - "offset": 0, - "slot": "7" - } - ], - "numberOfBytes": "256" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "a442464e95ddd6d4eb5a195f3edcbab69d12df336c03a47e889ae54493f98ad1": { - "address": "0x6A630D781aD6cf0D695E8863C264E057F842C768", - "txHash": "0xe495f2b64c8601daff852d7c8a294e6523c3be117044a0c73f2ef1bd9260378b", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:62", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:67" + "slot": "157", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:40" }, { "label": "__gap", "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\utils\\ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:22" + "slot": "158", + "type": "t_array(t_uint256)44_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:514" }, { "label": "__gap", "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:94" - }, - { - "label": "_trustedForwarders", - "offset": 0, - "slot": "101", - "type": "t_mapping(t_address,t_bool)", - "contract": "ERC2771RecipientUpgradeable", - "src": "contracts\\libs\\ERC2771RecipientUpgradeable.sol:29" - }, - { - "label": "_paused", - "offset": 0, - "slot": "102", - "type": "t_bool", - "contract": "PausableUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\security\\PausableUpgradeable.sol:29" + "slot": "202", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:211" }, { "label": "__gap", "offset": 0, - "slot": "103", - "type": "t_array(t_uint256)49_storage", - "contract": "PausableUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\security\\PausableUpgradeable.sol:116" + "slot": "252", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:107" }, { - "label": "__gap", + "label": "talentLayerPlatformIdContract", "offset": 0, - "slot": "152", - "type": "t_array(t_uint256)50_storage", - "contract": "ERC1967UpgradeUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\ERC1967\\ERC1967UpgradeUpgradeable.sol:211" + "slot": "302", + "type": "t_contract(ITalentLayerPlatformID)7478", + "contract": "TalentLayerID", + "src": "contracts/TalentLayerID.sol:70" }, { - "label": "__gap", + "label": "takenHandles", "offset": 0, - "slot": "202", - "type": "t_array(t_uint256)50_storage", - "contract": "UUPSUpgradeable", - "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\UUPSUpgradeable.sol:107" + "slot": "303", + "type": "t_mapping(t_string_memory_ptr,t_bool)", + "contract": "TalentLayerID", + "src": "contracts/TalentLayerID.sol:75" }, { - "label": "transactions", + "label": "profiles", "offset": 0, - "slot": "252", - "type": "t_mapping(t_uint256,t_struct(Transaction)2287_storage)", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:280" + "slot": "304", + "type": "t_mapping(t_uint256,t_struct(Profile)4707_storage)", + "contract": "TalentLayerID", + "src": "contracts/TalentLayerID.sol:80" }, { - "label": "platformIdToTokenToBalance", + "label": "ids", "offset": 0, - "slot": "253", - "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:289" + "slot": "305", + "type": "t_mapping(t_address,t_uint256)", + "contract": "TalentLayerID", + "src": "contracts/TalentLayerID.sol:85" }, { - "label": "talentLayerServiceContract", + "label": "mintFee", "offset": 0, - "slot": "254", - "type": "t_contract(ITalentLayerService)5231", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:294" + "slot": "306", + "type": "t_uint256", + "contract": "TalentLayerID", + "src": "contracts/TalentLayerID.sol:90" }, { - "label": "talentLayerIdContract", + "label": "nextProfileId", "offset": 0, - "slot": "255", - "type": "t_contract(ITalentLayerID)4861", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:299" + "slot": "307", + "type": "t_struct(Counter)2768_storage", + "contract": "TalentLayerID", + "src": "contracts/TalentLayerID.sol:95" }, { - "label": "talentLayerPlatformIdContract", + "label": "delegates", "offset": 0, - "slot": "256", - "type": "t_contract(ITalentLayerPlatformID)5073", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:304" + "slot": "308", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_bool))", + "contract": "TalentLayerID", + "src": "contracts/TalentLayerID.sol:100" }, { - "label": "protocolWallet", + "label": "whitelistMerkleRoot", "offset": 0, - "slot": "257", - "type": "t_address_payable", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:309" + "slot": "309", + "type": "t_bytes32", + "contract": "TalentLayerID", + "src": "contracts/TalentLayerID.sol:105" }, { - "label": "protocolEscrowFeeRate", - "offset": 20, - "slot": "257", - "type": "t_uint16", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:314" + "label": "mintStatus", + "offset": 0, + "slot": "310", + "type": "t_enum(MintStatus)4698", + "contract": "TalentLayerID", + "src": "contracts/TalentLayerID.sol:110" }, { - "label": "disputeIDtoTransactionID", + "label": "shortHandlesMaxPrice", "offset": 0, - "slot": "258", - "type": "t_mapping(t_uint256,t_uint256)", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:344" + "slot": "311", + "type": "t_uint256", + "contract": "TalentLayerID", + "src": "contracts/TalentLayerID.sol:115" }, { - "label": "nextTransactionId", + "label": "hasActivity", "offset": 0, - "slot": "259", - "type": "t_struct(Counter)1819_storage", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:349" + "slot": "312", + "type": "t_mapping(t_uint256,t_bool)", + "contract": "TalentLayerID", + "src": "contracts/TalentLayerID.sol:120" }, { - "label": "referrerIdToTokenToBalance", + "label": "isServiceContract", "offset": 0, - "slot": "260", - "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", - "contract": "TalentLayerEscrow", - "src": "contracts\\TalentLayerEscrow.sol:357" + "slot": "313", + "type": "t_mapping(t_address,t_bool)", + "contract": "TalentLayerID", + "src": "contracts/TalentLayerID.sol:125" } ], "types": { @@ -4008,9 +2498,9 @@ "label": "address", "numberOfBytes": "20" }, - "t_address_payable": { - "label": "address payable", - "numberOfBytes": "20" + "t_array(t_uint256)44_storage": { + "label": "uint256[44]", + "numberOfBytes": "1408" }, "t_array(t_uint256)49_storage": { "label": "uint256[49]", @@ -4024,34 +2514,20 @@ "label": "bool", "numberOfBytes": "1" }, - "t_bytes_storage": { - "label": "bytes", + "t_bytes32": { + "label": "bytes32", "numberOfBytes": "32" }, - "t_contract(Arbitrator)2187": { - "label": "contract Arbitrator", - "numberOfBytes": "20" - }, - "t_contract(ITalentLayerID)4861": { - "label": "contract ITalentLayerID", - "numberOfBytes": "20" - }, - "t_contract(ITalentLayerPlatformID)5073": { + "t_contract(ITalentLayerPlatformID)7478": { "label": "contract ITalentLayerPlatformID", "numberOfBytes": "20" }, - "t_contract(ITalentLayerService)5231": { - "label": "contract ITalentLayerService", - "numberOfBytes": "20" - }, - "t_enum(Status)2240": { - "label": "enum TalentLayerEscrow.Status", + "t_enum(MintStatus)4698": { + "label": "enum TalentLayerID.MintStatus", "members": [ - "NoDispute", - "WaitingSender", - "WaitingReceiver", - "DisputeCreated", - "Resolved" + "ON_PAUSE", + "ONLY_WHITELIST", + "PUBLIC" ], "numberOfBytes": "1" }, @@ -4059,23 +2535,43 @@ "label": "mapping(address => bool)", "numberOfBytes": "32" }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32" + }, "t_mapping(t_address,t_uint256)": { "label": "mapping(address => uint256)", "numberOfBytes": "32" }, - "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { - "label": "mapping(uint256 => mapping(address => uint256))", + "t_mapping(t_string_memory_ptr,t_bool)": { + "label": "mapping(string => bool)", "numberOfBytes": "32" }, - "t_mapping(t_uint256,t_struct(Transaction)2287_storage)": { - "label": "mapping(uint256 => struct TalentLayerEscrow.Transaction)", + "t_mapping(t_uint256,t_address)": { + "label": "mapping(uint256 => address)", "numberOfBytes": "32" }, - "t_mapping(t_uint256,t_uint256)": { - "label": "mapping(uint256 => uint256)", + "t_mapping(t_uint256,t_bool)": { + "label": "mapping(uint256 => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_bool))": { + "label": "mapping(uint256 => mapping(address => bool))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Profile)4707_storage)": { + "label": "mapping(uint256 => struct TalentLayerID.Profile)", + "numberOfBytes": "32" + }, + "t_string_memory_ptr": { + "label": "string", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", "numberOfBytes": "32" }, - "t_struct(Counter)1819_storage": { + "t_struct(Counter)2768_storage": { "label": "struct CountersUpgradeable.Counter", "members": [ { @@ -4087,8 +2583,8 @@ ], "numberOfBytes": "32" }, - "t_struct(Transaction)2287_storage": { - "label": "struct TalentLayerEscrow.Transaction", + "t_struct(Profile)4707_storage": { + "label": "struct TalentLayerID.Profile", "members": [ { "label": "id", @@ -4097,137 +2593,25 @@ "slot": "0" }, { - "label": "sender", - "type": "t_address", + "label": "handle", + "type": "t_string_storage", "offset": 0, "slot": "1" }, { - "label": "receiver", - "type": "t_address", + "label": "platformId", + "type": "t_uint256", "offset": 0, "slot": "2" }, { - "label": "token", - "type": "t_address", + "label": "dataUri", + "type": "t_string_storage", "offset": 0, "slot": "3" - }, - { - "label": "amount", - "type": "t_uint256", - "offset": 0, - "slot": "4" - }, - { - "label": "releasedAmount", - "type": "t_uint256", - "offset": 0, - "slot": "5" - }, - { - "label": "serviceId", - "type": "t_uint256", - "offset": 0, - "slot": "6" - }, - { - "label": "proposalId", - "type": "t_uint256", - "offset": 0, - "slot": "7" - }, - { - "label": "protocolEscrowFeeRate", - "type": "t_uint16", - "offset": 0, - "slot": "8" - }, - { - "label": "originServiceFeeRate", - "type": "t_uint16", - "offset": 2, - "slot": "8" - }, - { - "label": "originValidatedProposalFeeRate", - "type": "t_uint16", - "offset": 4, - "slot": "8" - }, - { - "label": "arbitrator", - "type": "t_contract(Arbitrator)2187", - "offset": 6, - "slot": "8" - }, - { - "label": "status", - "type": "t_enum(Status)2240", - "offset": 26, - "slot": "8" - }, - { - "label": "disputeId", - "type": "t_uint256", - "offset": 0, - "slot": "9" - }, - { - "label": "senderFee", - "type": "t_uint256", - "offset": 0, - "slot": "10" - }, - { - "label": "receiverFee", - "type": "t_uint256", - "offset": 0, - "slot": "11" - }, - { - "label": "lastInteraction", - "type": "t_uint256", - "offset": 0, - "slot": "12" - }, - { - "label": "arbitratorExtraData", - "type": "t_bytes_storage", - "offset": 0, - "slot": "13" - }, - { - "label": "arbitrationFeeTimeout", - "type": "t_uint256", - "offset": 0, - "slot": "14" - }, - { - "label": "referrerId", - "type": "t_uint256", - "offset": 0, - "slot": "15" - }, - { - "label": "referralAmount", - "type": "t_uint256", - "offset": 0, - "slot": "16" - }, - { - "label": "totalAmount", - "type": "t_uint256", - "offset": 0, - "slot": "17" } ], - "numberOfBytes": "576" - }, - "t_uint16": { - "label": "uint16", - "numberOfBytes": "2" + "numberOfBytes": "128" }, "t_uint256": { "label": "uint256", From 7f84e7a41acc583680f13c5bd43f4d37028424bd Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Fri, 28 Jul 2023 22:02:07 +0200 Subject: [PATCH 93/99] Update Natspec Signed-off-by: Quentin D.C --- contracts/TalentLayerEscrow.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index 1b8ef4f1..6477afa6 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -759,7 +759,7 @@ contract TalentLayerEscrow is * @notice Allows a platform owner to claim its tokens & / or ETH balance. * @param _platformId The ID of the platform claiming the balance. * @param _tokenAddress The address of the Token contract (address(0) if balance in ETH). - * Emits a BalanceTransferred event + * Emits a FeesClaimed event */ function claim(uint256 _platformId, address _tokenAddress) external whenNotPaused { address payable recipient; @@ -786,7 +786,7 @@ contract TalentLayerEscrow is * @notice Allows a referrer to claim its tokens & / or ETH balance. * @param _referrerId The ID of the referrer claiming the balance. * @param _tokenAddress The address of the Token contract (address(0) if balance in ETH). - * @dev Emits a BalanceTransferred & a ReferralAmountClaimed events + * @dev Emits a ReferralAmountClaimed events */ function claimReferralBalance(uint256 _referrerId, address _tokenAddress) external whenNotPaused { address payable recipient; From 0de07fc5ed4296eaed08f7e769d46df2c22da532 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Thu, 30 Nov 2023 17:28:25 +0000 Subject: [PATCH 94/99] Added missing + ! --- contracts/TalentLayerEscrow.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/TalentLayerEscrow.sol b/contracts/TalentLayerEscrow.sol index e0b1f03a..eaa1d710 100644 --- a/contracts/TalentLayerEscrow.sol +++ b/contracts/TalentLayerEscrow.sol @@ -1018,7 +1018,7 @@ contract TalentLayerEscrow is if (transaction.referrerId != 0 && transaction.referralAmount != 0) { uint256 releasedReferralAmount = (_releaseAmount * transaction.referralAmount) / (transaction.totalAmount); - referrerIdToTokenToBalance[transaction.referrerId][transaction.token] = releasedReferralAmount; + referrerIdToTokenToBalance[transaction.referrerId][transaction.token] += releasedReferralAmount; emit ReferralAmountReleased( transaction.referrerId, From be8626996ce5402d340e10ed4321b5e642a8eb9b Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Fri, 1 Dec 2023 15:37:49 +0000 Subject: [PATCH 95/99] Updated updateService function --- contracts/TalentLayerService.sol | 9 +++++++-- test/batch/delegationSystem.ts | 2 +- test/batch/fullWorkflow.ts | 15 ++++++++++----- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/contracts/TalentLayerService.sol b/contracts/TalentLayerService.sol index 7fb880fb..259cf1ca 100644 --- a/contracts/TalentLayerService.sol +++ b/contracts/TalentLayerService.sol @@ -121,9 +121,10 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @notice Emit when data is updated for a Service * @param id The service ID * @param dataUri New service Data URI + * @param rateToken token address to be used for the service's payments * @param referralAmount New referral amount */ - event ServiceUpdated(uint256 id, string dataUri, uint256 referralAmount); + event ServiceUpdated(uint256 id, string dataUri, address rateToken, uint256 referralAmount); /** * @notice Emitted after a new proposal is created @@ -353,12 +354,14 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @notice Update Service URI data * @param _profileId The TalentLayer ID of the user, owner of the service * @param _serviceId, Service ID to update + * @param _rateToken token address to be used for the service's payments * @param _referralAmount, New referral amount * @param _dataUri New IPFS URI */ function updateService( uint256 _profileId, uint256 _serviceId, + address _rateToken, uint256 _referralAmount, string calldata _dataUri ) public onlyOwnerOrDelegate(_profileId) { @@ -366,12 +369,14 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU require(service.ownerId == _profileId, "Not the owner"); require(service.status == Status.Opened, "status must be opened"); require(bytes(_dataUri).length == 46, "Invalid cid"); + require(allowedTokenList[_rateToken].isWhitelisted, "Token not allowed"); require(_referralAmount >= service.referralAmount, "Can't reduce referral amount"); service.dataUri = _dataUri; service.referralAmount = _referralAmount; + service.rateToken = _rateToken; - emit ServiceUpdated(_serviceId, _dataUri, _referralAmount); + emit ServiceUpdated(_serviceId, _dataUri, _rateToken, _referralAmount); } /** diff --git a/test/batch/delegationSystem.ts b/test/batch/delegationSystem.ts index 1ec120ef..38504ee1 100644 --- a/test/batch/delegationSystem.ts +++ b/test/batch/delegationSystem.ts @@ -144,7 +144,7 @@ describe('Delegation System', function () { }) it('Dave can update service data on behalf of Alice', async function () { - const tx = await talentLayerService.connect(dave).updateService(aliceTlId, serviceId, 0, cid) + const tx = await talentLayerService.connect(dave).updateService(aliceTlId, serviceId, ethers.constants.AddressZero, referralAmount, cid) await expect(tx).to.not.be.reverted }) diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index c76084e4..59ce2ac3 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -859,6 +859,7 @@ describe('TalentLayer protocol global testing', function () { expect(service1Data.dataUri).to.be.equal(cid) expect(service1Data.platformId).to.be.equal(1) expect(service1Data.referralAmount).to.be.equal(0) + expect(service1Data.rateToken).to.be.equal(token.address) expect(tx) .to.emit(talentLayerService, 'ServiceCreated') .withArgs(5, aliceTlId, alicePlatformId, cid, token.address, 0) @@ -930,25 +931,29 @@ describe('TalentLayer protocol global testing', function () { }) it('Alice can update her service data', async function () { - await talentLayerService.connect(alice).updateService(aliceTlId, 1, referralAmount, cid2) + await talentLayerService.connect(alice).updateService(aliceTlId, 1, ethers.constants.AddressZero, referralAmount, cid2) const serviceData = await talentLayerService.services(1) expect(serviceData.dataUri).to.be.equal(cid2) + expect(serviceData.rateToken).to.be.equal(ethers.constants.AddressZero) + // Revert update + await talentLayerService.connect(alice).updateService(aliceTlId, 1, token.address, referralAmount, cid2) + const newReferralAmount = 40000 const tx = await talentLayerService .connect(alice) - .updateService(aliceTlId, 6, newReferralAmount, cid2) + .updateService(aliceTlId, 6, ethers.constants.AddressZero, newReferralAmount, cid2) const service6Data = await talentLayerService.services(6) expect(tx) .to.emit(talentLayerService, 'ServiceUpdated') - .withArgs(6, cid2, newReferralAmount, ethers.constants.AddressZero) + .withArgs(6, cid2, ethers.constants.AddressZero, newReferralAmount) expect(service6Data.referralAmount).to.be.equal(newReferralAmount) }) it('Alice cannot update her service with an inferior referral amount', async function () { await expect( - talentLayerService.connect(alice).updateService(aliceTlId, 1, referralAmount - 1, cid2), + talentLayerService.connect(alice).updateService(aliceTlId, 1, token.address, referralAmount - 1, cid2), ).to.be.revertedWith("Can't reduce referral amount") }) @@ -1536,7 +1541,7 @@ describe('TalentLayer protocol global testing', function () { it('Alice cannot update her service data after it is confirmed', async function () { const tx = talentLayerService .connect(alice) - .updateService(aliceTlId, serviceId, referralAmount, cid2) + .updateService(aliceTlId, serviceId, ethers.constants.AddressZero, referralAmount, cid2) await expect(tx).to.be.revertedWith('status must be opened') }) From fcd11532bc033932eef3532d595e8041303d621e Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Fri, 1 Dec 2023 16:16:21 +0000 Subject: [PATCH 96/99] Updated Playground --- scripts/playground/2-create-service.ts | 5 ++++- scripts/playground/2-update-service.ts | 3 ++- scripts/playground/3-make-proposal.ts | 7 ++++--- scripts/playground/4-update-proposal.ts | 3 ++- scripts/playground/8-reviews.ts | 2 +- 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/scripts/playground/2-create-service.ts b/scripts/playground/2-create-service.ts index b0829393..36077519 100644 --- a/scripts/playground/2-create-service.ts +++ b/scripts/playground/2-create-service.ts @@ -5,6 +5,7 @@ import { getSignatureForService } from '../../test/utils/signature' import hre = require('hardhat') const aliceTlId = 1 +const referralAmount = 0 /* In this script Alice will create two services. @@ -56,7 +57,7 @@ async function main() { const createFirstOpenService = await talentLayerService .connect(alice) - .createService(aliceTlId, daveTalentLayerIdPlatform, aliceCreateFirstJobData, signatureFirstJob) + .createService(aliceTlId, daveTalentLayerIdPlatform, aliceCreateFirstJobData, signatureFirstJob, ethers.constants.AddressZero, referralAmount) await createFirstOpenService.wait() console.log('First Open Service created') @@ -91,6 +92,8 @@ async function main() { daveTalentLayerIdPlatform, aliceCreateSecondJobData, signatureSecondJob, + ethers.constants.AddressZero, + referralAmount, ) await createSecondOpenService.wait() console.log('Open Service 2 created') diff --git a/scripts/playground/2-update-service.ts b/scripts/playground/2-update-service.ts index 4470d5cb..ea307d1d 100644 --- a/scripts/playground/2-update-service.ts +++ b/scripts/playground/2-update-service.ts @@ -4,6 +4,7 @@ import postToIPFS from '../utils/ipfs' import hre = require('hardhat') const aliceTlId = 1 +const referralAmount = 0 /* In this script Alice will update the first service. @@ -49,7 +50,7 @@ async function main() { await talentLayerService .connect(alice) - .updateServiceData(aliceTlId, firstServiceId, aliceUpdateJobData) + .updateService(aliceTlId, firstServiceId, ethers.constants.AddressZero, referralAmount, aliceUpdateJobData) const jobDataAfterUpdate = await talentLayerService.getService(firstServiceId) console.log('Job Data after update', jobDataAfterUpdate) } diff --git a/scripts/playground/3-make-proposal.ts b/scripts/playground/3-make-proposal.ts index 4417c69b..b2a5a00f 100644 --- a/scripts/playground/3-make-proposal.ts +++ b/scripts/playground/3-make-proposal.ts @@ -7,6 +7,7 @@ const aliceTlId = 1 const bobTlId = 2 const carolTlId = 3 const daveTlId = 4 +const referrerTlId = 0 const minTokenWhitelistTransactionAmount = ethers.utils.parseUnits('0.0001', 18) @@ -101,12 +102,12 @@ async function main() { .createProposal( bobTlId, firstServiceId, - rateTokenBob, ethers.utils.parseUnits('0.001', 18), davePlatformId, bobUri, proposalExpirationDate, signatureBobProposal, + referrerTlId, ) console.log('Bob proposal created') await bobProposal.wait() @@ -124,12 +125,12 @@ async function main() { .createProposal( carolTlId, firstServiceId, - rateTokenCarol, ethers.utils.parseUnits('0.002', 18), bobPlatformId, carolUri, proposalExpirationDate, signatureCarolProposal, + referrerTlId, ) console.log('Carol proposal created') await carolProposal.wait() @@ -147,12 +148,12 @@ async function main() { .createProposal( daveTlId, secondServiceId, - rateTokenDave, ethers.utils.parseUnits('0.003', 18), bobPlatformId, daveUri, proposalExpirationDate, signatureDaveProposal, + referrerTlId, ) console.log('Dave proposal created') await daveProposal.wait() diff --git a/scripts/playground/4-update-proposal.ts b/scripts/playground/4-update-proposal.ts index 26a83c5d..2e0c514c 100644 --- a/scripts/playground/4-update-proposal.ts +++ b/scripts/playground/4-update-proposal.ts @@ -4,6 +4,7 @@ import postToIPFS from '../utils/ipfs' import hre = require('hardhat') const bobTlId = 2 +const referrerTlId = 0 const now = Math.floor(Date.now() / 1000) const proposalExpirationDate = now + 60 * 60 * 24 * 30 @@ -41,10 +42,10 @@ async function main() { .updateProposal( bobTlId, firstServiceId, - rateTokenBob, ethers.utils.parseUnits('0.0015', 18), bobUri, proposalExpirationDate, + referrerTlId, ) console.log('Bob update his proposal') diff --git a/scripts/playground/8-reviews.ts b/scripts/playground/8-reviews.ts index 2336544d..d0882b2b 100644 --- a/scripts/playground/8-reviews.ts +++ b/scripts/playground/8-reviews.ts @@ -18,7 +18,7 @@ async function main() { const talentLayerReview = await ethers.getContractAt( 'TalentLayerReview', - getDeploymentProperty(network, DeploymentProperty.Reviewscontract), + getDeploymentProperty(network, DeploymentProperty.TalentLayerReview), ) const aliceReviewCarol = await postToIPFS( From 797bd9950896719b6910c56e1daccf3b5e7bb57c Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Fri, 1 Dec 2023 17:49:11 +0000 Subject: [PATCH 97/99] Reverted updateService change --- .openzeppelin/polygon-mumbai.json | 1819 ++++++++++++++++++++++-- contracts/TalentLayerService.sol | 9 +- scripts/playground/2-update-service.ts | 2 +- test/batch/delegationSystem.ts | 2 +- test/batch/fullWorkflow.ts | 14 +- 5 files changed, 1694 insertions(+), 152 deletions(-) diff --git a/.openzeppelin/polygon-mumbai.json b/.openzeppelin/polygon-mumbai.json index 96dd0d0f..b05e56cb 100644 --- a/.openzeppelin/polygon-mumbai.json +++ b/.openzeppelin/polygon-mumbai.json @@ -25,6 +25,46 @@ "address": "0x4bE920eC3e8552292B2147480111063E0dc36872", "txHash": "0xb2eccc32f9e60d7bbb7b0297ff37ae643a2c0bab4946c86f5ceccbda77e7d03e", "kind": "uups" + }, + { + "address": "0x9Edaa157da3c9963175E806ce0F439F13e4151Fb", + "txHash": "0xd6ee5eed488df7d4d82e808a90b155691d2dd41653e8909af6260ab77ff9f3b5", + "kind": "uups" + }, + { + "address": "0xF5F2CF3Ae1F89a617fD55DC88c255FDEfCAEd72b", + "txHash": "0x8352ee7c8568ec6ed2fb6bf7a6277d3eeb7764cb353db1188764443e7c72a3e6", + "kind": "uups" + }, + { + "address": "0x1FA9fd795ac8a3e4DD267497F4227Ee58FBe0e04", + "txHash": "0x26d37dd00b59523651177456ec0761458a2a80de8d28274e5bcbb318f224478d", + "kind": "uups" + }, + { + "address": "0x65bd3250bF6493b6a0b3f5438A18591Ff803c996", + "txHash": "0xb0887b61e5c159f898c4bd8019b7d89762eb5c36da5068c328ccdb41e740a5a3", + "kind": "uups" + }, + { + "address": "0x57384B08DF816D540D1ac3B436716d092bEbe4Bc", + "txHash": "0x4ff75e98a96cb17382d9d01a8587645be847b0679d882a171ba81a1bd9d3dba3", + "kind": "uups" + }, + { + "address": "0xbd4098244759c72F8A64307e1fe5Ae34b3B818C2", + "txHash": "0x0e97b4ed3da7ede9f907c7340f67843d28c6795f121948fd931aacc6e5030954", + "kind": "uups" + }, + { + "address": "0xc56B8Ca7E9Efd9533E10FaeE0813070aF0d93aAb", + "txHash": "0xc241b9b6200d817c83c5f875366b9fdaf1b5f8e20c70efe8ac4194f43b01fac5", + "kind": "uups" + }, + { + "address": "0x40c8784324Ac487c3E324D2f80727131e53B9965", + "txHash": "0x802535b7c2c7ffcc3cd6f1c69ebbe91cc9deea2842d3e96e9a75008f0191dc1e", + "kind": "uups" } ], "impls": { @@ -2261,9 +2301,9 @@ } } }, - "f9e7916a1c316964ab24794f96ac3ee47b57790f1fb37e7a459ebb7c82af0d2e": { - "address": "0x10f5FA91077E8F0Ce4791F998bFE7233216F7E76", - "txHash": "0x7446df365bae78c03532ab0e66f0b2943fddfb5bc45115fce95e90b5d72cc58b", + "5348791f129964f78be6e5dcfc9ba260df2c51b348774af103e0d5290d79ecb6": { + "address": "0x00821fEaC642fB6227d70F358687805A0aD30CF6", + "txHash": "0x2adb2f4430647694bb3eafbc046d7cdf96af21b2263e86d22e0df06011a2fcb1", "layout": { "solcVersion": "0.8.17", "storage": [ @@ -2273,7 +2313,7 @@ "slot": "0", "type": "t_uint8", "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:62", "retypedFrom": "bool" }, { @@ -2282,7 +2322,7 @@ "slot": "0", "type": "t_bool", "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:67" }, { "label": "__gap", @@ -2290,207 +2330,183 @@ "slot": "1", "type": "t_array(t_uint256)50_storage", "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_trustedForwarders", - "offset": 0, - "slot": "101", - "type": "t_mapping(t_address,t_bool)", - "contract": "ERC2771RecipientUpgradeable", - "src": "contracts/libs/ERC2771RecipientUpgradeable.sol:29" + "src": "@openzeppelin\\contracts-upgradeable\\utils\\ContextUpgradeable.sol:36" }, { "label": "__gap", "offset": 0, - "slot": "102", + "slot": "51", "type": "t_array(t_uint256)50_storage", "contract": "ERC165Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + "src": "@openzeppelin\\contracts-upgradeable\\utils\\introspection\\ERC165Upgradeable.sol:41" }, { "label": "_name", "offset": 0, - "slot": "152", + "slot": "101", "type": "t_string_storage", "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:25" + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:25" }, { "label": "_symbol", "offset": 0, - "slot": "153", + "slot": "102", "type": "t_string_storage", "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:28" + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:28" }, { "label": "_owners", "offset": 0, - "slot": "154", + "slot": "103", "type": "t_mapping(t_uint256,t_address)", "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:31" + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:31" }, { "label": "_balances", "offset": 0, - "slot": "155", + "slot": "104", "type": "t_mapping(t_address,t_uint256)", "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:34" + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:34" }, { "label": "_tokenApprovals", "offset": 0, - "slot": "156", + "slot": "105", "type": "t_mapping(t_uint256,t_address)", "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:37" + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:37" }, { "label": "_operatorApprovals", "offset": 0, - "slot": "157", + "slot": "106", "type": "t_mapping(t_address,t_mapping(t_address,t_bool))", "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:40" + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:40" }, { "label": "__gap", "offset": 0, - "slot": "158", + "slot": "107", "type": "t_array(t_uint256)44_storage", "contract": "ERC721Upgradeable", - "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:514" + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:514" + }, + { + "label": "_roles", + "offset": 0, + "slot": "151", + "type": "t_mapping(t_bytes32,t_struct(RoleData)58_storage)", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\AccessControlUpgradeable.sol:61" }, { "label": "__gap", "offset": 0, - "slot": "202", + "slot": "152", + "type": "t_array(t_uint256)49_storage", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\AccessControlUpgradeable.sol:259" + }, + { + "label": "__gap", + "offset": 0, + "slot": "201", "type": "t_array(t_uint256)50_storage", "contract": "ERC1967UpgradeUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:211" + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\ERC1967\\ERC1967UpgradeUpgradeable.sol:211" }, { "label": "__gap", "offset": 0, - "slot": "252", + "slot": "251", "type": "t_array(t_uint256)50_storage", "contract": "UUPSUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:107" + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\UUPSUpgradeable.sol:107" }, { - "label": "talentLayerPlatformIdContract", + "label": "takenNames", + "offset": 0, + "slot": "301", + "type": "t_mapping(t_string_memory_ptr,t_bool)", + "contract": "TalentLayerPlatformID", + "src": "contracts\\TalentLayerPlatformID.sol:65" + }, + { + "label": "platforms", "offset": 0, "slot": "302", - "type": "t_contract(ITalentLayerPlatformID)7478", - "contract": "TalentLayerID", - "src": "contracts/TalentLayerID.sol:70" + "type": "t_mapping(t_uint256,t_struct(Platform)12988_storage)", + "contract": "TalentLayerPlatformID", + "src": "contracts\\TalentLayerPlatformID.sol:70" }, { - "label": "takenHandles", + "label": "validArbitrators", "offset": 0, "slot": "303", - "type": "t_mapping(t_string_memory_ptr,t_bool)", - "contract": "TalentLayerID", - "src": "contracts/TalentLayerID.sol:75" + "type": "t_mapping(t_address,t_bool)", + "contract": "TalentLayerPlatformID", + "src": "contracts\\TalentLayerPlatformID.sol:75" }, { - "label": "profiles", + "label": "whitelist", "offset": 0, "slot": "304", - "type": "t_mapping(t_uint256,t_struct(Profile)4707_storage)", - "contract": "TalentLayerID", - "src": "contracts/TalentLayerID.sol:80" + "type": "t_mapping(t_address,t_bool)", + "contract": "TalentLayerPlatformID", + "src": "contracts\\TalentLayerPlatformID.sol:80" }, { - "label": "ids", + "label": "internalArbitrators", "offset": 0, "slot": "305", - "type": "t_mapping(t_address,t_uint256)", - "contract": "TalentLayerID", - "src": "contracts/TalentLayerID.sol:85" + "type": "t_mapping(t_address,t_bool)", + "contract": "TalentLayerPlatformID", + "src": "contracts\\TalentLayerPlatformID.sol:86" }, { - "label": "mintFee", + "label": "ids", "offset": 0, "slot": "306", - "type": "t_uint256", - "contract": "TalentLayerID", - "src": "contracts/TalentLayerID.sol:90" + "type": "t_mapping(t_address,t_uint256)", + "contract": "TalentLayerPlatformID", + "src": "contracts\\TalentLayerPlatformID.sol:91" }, { - "label": "nextProfileId", + "label": "mintFee", "offset": 0, "slot": "307", - "type": "t_struct(Counter)2768_storage", - "contract": "TalentLayerID", - "src": "contracts/TalentLayerID.sol:95" + "type": "t_uint256", + "contract": "TalentLayerPlatformID", + "src": "contracts\\TalentLayerPlatformID.sol:96" }, { - "label": "delegates", + "label": "minArbitrationFeeTimeout", "offset": 0, "slot": "308", - "type": "t_mapping(t_uint256,t_mapping(t_address,t_bool))", - "contract": "TalentLayerID", - "src": "contracts/TalentLayerID.sol:100" + "type": "t_uint256", + "contract": "TalentLayerPlatformID", + "src": "contracts\\TalentLayerPlatformID.sol:106" }, { - "label": "whitelistMerkleRoot", + "label": "nextPlatformId", "offset": 0, "slot": "309", - "type": "t_bytes32", - "contract": "TalentLayerID", - "src": "contracts/TalentLayerID.sol:105" + "type": "t_struct(Counter)3290_storage", + "contract": "TalentLayerPlatformID", + "src": "contracts\\TalentLayerPlatformID.sol:111" }, { "label": "mintStatus", "offset": 0, "slot": "310", - "type": "t_enum(MintStatus)4698", - "contract": "TalentLayerID", - "src": "contracts/TalentLayerID.sol:110" - }, - { - "label": "shortHandlesMaxPrice", - "offset": 0, - "slot": "311", - "type": "t_uint256", - "contract": "TalentLayerID", - "src": "contracts/TalentLayerID.sol:115" - }, - { - "label": "hasActivity", - "offset": 0, - "slot": "312", - "type": "t_mapping(t_uint256,t_bool)", - "contract": "TalentLayerID", - "src": "contracts/TalentLayerID.sol:120" - }, - { - "label": "isServiceContract", - "offset": 0, - "slot": "313", - "type": "t_mapping(t_address,t_bool)", - "contract": "TalentLayerID", - "src": "contracts/TalentLayerID.sol:125" + "type": "t_enum(MintStatus)12964", + "contract": "TalentLayerPlatformID", + "src": "contracts\\TalentLayerPlatformID.sol:116" } ], "types": { @@ -2518,12 +2534,16 @@ "label": "bytes32", "numberOfBytes": "32" }, - "t_contract(ITalentLayerPlatformID)7478": { - "label": "contract ITalentLayerPlatformID", + "t_bytes_storage": { + "label": "bytes", + "numberOfBytes": "32" + }, + "t_contract(Arbitrator)7789": { + "label": "contract Arbitrator", "numberOfBytes": "20" }, - "t_enum(MintStatus)4698": { - "label": "enum TalentLayerID.MintStatus", + "t_enum(MintStatus)12964": { + "label": "enum TalentLayerPlatformID.MintStatus", "members": [ "ON_PAUSE", "ONLY_WHITELIST", @@ -2543,6 +2563,10 @@ "label": "mapping(address => uint256)", "numberOfBytes": "32" }, + "t_mapping(t_bytes32,t_struct(RoleData)58_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32" + }, "t_mapping(t_string_memory_ptr,t_bool)": { "label": "mapping(string => bool)", "numberOfBytes": "32" @@ -2551,16 +2575,8 @@ "label": "mapping(uint256 => address)", "numberOfBytes": "32" }, - "t_mapping(t_uint256,t_bool)": { - "label": "mapping(uint256 => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_mapping(t_address,t_bool))": { - "label": "mapping(uint256 => mapping(address => bool))", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_struct(Profile)4707_storage)": { - "label": "mapping(uint256 => struct TalentLayerID.Profile)", + "t_mapping(t_uint256,t_struct(Platform)12988_storage)": { + "label": "mapping(uint256 => struct TalentLayerPlatformID.Platform)", "numberOfBytes": "32" }, "t_string_memory_ptr": { @@ -2571,7 +2587,7 @@ "label": "string", "numberOfBytes": "32" }, - "t_struct(Counter)2768_storage": { + "t_struct(Counter)3290_storage": { "label": "struct CountersUpgradeable.Counter", "members": [ { @@ -2583,8 +2599,8 @@ ], "numberOfBytes": "32" }, - "t_struct(Profile)4707_storage": { - "label": "struct TalentLayerID.Profile", + "t_struct(Platform)12988_storage": { + "label": "struct TalentLayerPlatformID.Platform", "members": [ { "label": "id", @@ -2593,25 +2609,1560 @@ "slot": "0" }, { - "label": "handle", + "label": "name", "type": "t_string_storage", "offset": 0, "slot": "1" }, { - "label": "platformId", - "type": "t_uint256", + "label": "dataUri", + "type": "t_string_storage", "offset": 0, "slot": "2" }, { - "label": "dataUri", - "type": "t_string_storage", + "label": "originServiceFeeRate", + "type": "t_uint16", "offset": 0, "slot": "3" - } - ], - "numberOfBytes": "128" + }, + { + "label": "originValidatedProposalFeeRate", + "type": "t_uint16", + "offset": 2, + "slot": "3" + }, + { + "label": "servicePostingFee", + "type": "t_uint256", + "offset": 0, + "slot": "4" + }, + { + "label": "proposalPostingFee", + "type": "t_uint256", + "offset": 0, + "slot": "5" + }, + { + "label": "arbitrator", + "type": "t_contract(Arbitrator)7789", + "offset": 0, + "slot": "6" + }, + { + "label": "arbitratorExtraData", + "type": "t_bytes_storage", + "offset": 0, + "slot": "7" + }, + { + "label": "arbitrationFeeTimeout", + "type": "t_uint256", + "offset": 0, + "slot": "8" + }, + { + "label": "signer", + "type": "t_address", + "offset": 0, + "slot": "9" + } + ], + "numberOfBytes": "320" + }, + "t_struct(RoleData)58_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)", + "offset": 0, + "slot": "0" + }, + { + "label": "adminRole", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "f9e7916a1c316964ab24794f96ac3ee47b57790f1fb37e7a459ebb7c82af0d2e": { + "address": "0x2c4d94b4A4cb80d6241cAc36Df4173CFdB285093", + "txHash": "0x2f047ceb43c62e4d1fb26fcf77a2f026c86fc6c69f53db5aea0fab6479c44e09", + "layout": { + "solcVersion": "0.8.17", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\utils\\ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:94" + }, + { + "label": "_trustedForwarders", + "offset": 0, + "slot": "101", + "type": "t_mapping(t_address,t_bool)", + "contract": "ERC2771RecipientUpgradeable", + "src": "contracts\\libs\\ERC2771RecipientUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC165Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\utils\\introspection\\ERC165Upgradeable.sol:41" + }, + { + "label": "_name", + "offset": 0, + "slot": "152", + "type": "t_string_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:25" + }, + { + "label": "_symbol", + "offset": 0, + "slot": "153", + "type": "t_string_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:28" + }, + { + "label": "_owners", + "offset": 0, + "slot": "154", + "type": "t_mapping(t_uint256,t_address)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:31" + }, + { + "label": "_balances", + "offset": 0, + "slot": "155", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:34" + }, + { + "label": "_tokenApprovals", + "offset": 0, + "slot": "156", + "type": "t_mapping(t_uint256,t_address)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:37" + }, + { + "label": "_operatorApprovals", + "offset": 0, + "slot": "157", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:40" + }, + { + "label": "__gap", + "offset": 0, + "slot": "158", + "type": "t_array(t_uint256)44_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:514" + }, + { + "label": "__gap", + "offset": 0, + "slot": "202", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\ERC1967\\ERC1967UpgradeUpgradeable.sol:211" + }, + { + "label": "__gap", + "offset": 0, + "slot": "252", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\UUPSUpgradeable.sol:107" + }, + { + "label": "talentLayerPlatformIdContract", + "offset": 0, + "slot": "302", + "type": "t_contract(ITalentLayerPlatformID)22226", + "contract": "TalentLayerID", + "src": "contracts\\TalentLayerID.sol:70" + }, + { + "label": "takenHandles", + "offset": 0, + "slot": "303", + "type": "t_mapping(t_string_memory_ptr,t_bool)", + "contract": "TalentLayerID", + "src": "contracts\\TalentLayerID.sol:75" + }, + { + "label": "profiles", + "offset": 0, + "slot": "304", + "type": "t_mapping(t_uint256,t_struct(Profile)11725_storage)", + "contract": "TalentLayerID", + "src": "contracts\\TalentLayerID.sol:80" + }, + { + "label": "ids", + "offset": 0, + "slot": "305", + "type": "t_mapping(t_address,t_uint256)", + "contract": "TalentLayerID", + "src": "contracts\\TalentLayerID.sol:85" + }, + { + "label": "mintFee", + "offset": 0, + "slot": "306", + "type": "t_uint256", + "contract": "TalentLayerID", + "src": "contracts\\TalentLayerID.sol:90" + }, + { + "label": "nextProfileId", + "offset": 0, + "slot": "307", + "type": "t_struct(Counter)3290_storage", + "contract": "TalentLayerID", + "src": "contracts\\TalentLayerID.sol:95" + }, + { + "label": "delegates", + "offset": 0, + "slot": "308", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_bool))", + "contract": "TalentLayerID", + "src": "contracts\\TalentLayerID.sol:100" + }, + { + "label": "whitelistMerkleRoot", + "offset": 0, + "slot": "309", + "type": "t_bytes32", + "contract": "TalentLayerID", + "src": "contracts\\TalentLayerID.sol:105" + }, + { + "label": "mintStatus", + "offset": 0, + "slot": "310", + "type": "t_enum(MintStatus)11716", + "contract": "TalentLayerID", + "src": "contracts\\TalentLayerID.sol:110" + }, + { + "label": "shortHandlesMaxPrice", + "offset": 0, + "slot": "311", + "type": "t_uint256", + "contract": "TalentLayerID", + "src": "contracts\\TalentLayerID.sol:115" + }, + { + "label": "hasActivity", + "offset": 0, + "slot": "312", + "type": "t_mapping(t_uint256,t_bool)", + "contract": "TalentLayerID", + "src": "contracts\\TalentLayerID.sol:120" + }, + { + "label": "isServiceContract", + "offset": 0, + "slot": "313", + "type": "t_mapping(t_address,t_bool)", + "contract": "TalentLayerID", + "src": "contracts\\TalentLayerID.sol:125" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)44_storage": { + "label": "uint256[44]", + "numberOfBytes": "1408" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(ITalentLayerPlatformID)22226": { + "label": "contract ITalentLayerPlatformID", + "numberOfBytes": "20" + }, + "t_enum(MintStatus)11716": { + "label": "enum TalentLayerID.MintStatus", + "members": [ + "ON_PAUSE", + "ONLY_WHITELIST", + "PUBLIC" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_string_memory_ptr,t_bool)": { + "label": "mapping(string => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_address)": { + "label": "mapping(uint256 => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_bool)": { + "label": "mapping(uint256 => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_bool))": { + "label": "mapping(uint256 => mapping(address => bool))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Profile)11725_storage)": { + "label": "mapping(uint256 => struct TalentLayerID.Profile)", + "numberOfBytes": "32" + }, + "t_string_memory_ptr": { + "label": "string", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Counter)3290_storage": { + "label": "struct CountersUpgradeable.Counter", + "members": [ + { + "label": "_value", + "type": "t_uint256", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(Profile)11725_storage": { + "label": "struct TalentLayerID.Profile", + "members": [ + { + "label": "id", + "type": "t_uint256", + "offset": 0, + "slot": "0" + }, + { + "label": "handle", + "type": "t_string_storage", + "offset": 0, + "slot": "1" + }, + { + "label": "platformId", + "type": "t_uint256", + "offset": 0, + "slot": "2" + }, + { + "label": "dataUri", + "type": "t_string_storage", + "offset": 0, + "slot": "3" + } + ], + "numberOfBytes": "128" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "fff83eb49b2b7484d73644074ce0abcc8ea1ec5506e30ab2473bc1a895b0c4c8": { + "address": "0xfBC702bFDE788B3df34d9aF93FfaD30C7B1D341f", + "txHash": "0xcd960e27b6ee76144df4a04aae0196913cbc389f36038dd971db7cf7fd86fb26", + "layout": { + "solcVersion": "0.8.17", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\utils\\ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:94" + }, + { + "label": "_trustedForwarders", + "offset": 0, + "slot": "101", + "type": "t_mapping(t_address,t_bool)", + "contract": "ERC2771RecipientUpgradeable", + "src": "contracts\\libs\\ERC2771RecipientUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\ERC1967\\ERC1967UpgradeUpgradeable.sol:211" + }, + { + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\UUPSUpgradeable.sol:107" + }, + { + "label": "__gap", + "offset": 0, + "slot": "202", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC165Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\utils\\introspection\\ERC165Upgradeable.sol:41" + }, + { + "label": "_roles", + "offset": 0, + "slot": "252", + "type": "t_mapping(t_bytes32,t_struct(RoleData)58_storage)", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\AccessControlUpgradeable.sol:61" + }, + { + "label": "__gap", + "offset": 0, + "slot": "253", + "type": "t_array(t_uint256)49_storage", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\AccessControlUpgradeable.sol:259" + }, + { + "label": "nextServiceId", + "offset": 0, + "slot": "302", + "type": "t_uint256", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:187" + }, + { + "label": "tlId", + "offset": 0, + "slot": "303", + "type": "t_contract(ITalentLayerID)22004", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:192" + }, + { + "label": "talentLayerPlatformIdContract", + "offset": 0, + "slot": "304", + "type": "t_contract(ITalentLayerPlatformID)22226", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:197" + }, + { + "label": "services", + "offset": 0, + "slot": "305", + "type": "t_mapping(t_uint256,t_struct(Service)14806_storage)", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:202" + }, + { + "label": "proposals", + "offset": 0, + "slot": "306", + "type": "t_mapping(t_uint256,t_mapping(t_uint256,t_struct(Proposal)14824_storage))", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:207" + }, + { + "label": "serviceNonce", + "offset": 0, + "slot": "307", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:212" + }, + { + "label": "proposalNonce", + "offset": 0, + "slot": "308", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:217" + }, + { + "label": "allowedTokenList", + "offset": 0, + "slot": "309", + "type": "t_mapping(t_address,t_struct(AllowedToken)14829_storage)", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:222" + }, + { + "label": "minCompletionPercentage", + "offset": 0, + "slot": "310", + "type": "t_uint256", + "contract": "TalentLayerService", + "src": "contracts\\TalentLayerService.sol:227" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(ITalentLayerID)22004": { + "label": "contract ITalentLayerID", + "numberOfBytes": "20" + }, + "t_contract(ITalentLayerPlatformID)22226": { + "label": "contract ITalentLayerPlatformID", + "numberOfBytes": "20" + }, + "t_enum(ProposalStatus)14788": { + "label": "enum TalentLayerService.ProposalStatus", + "members": [ + "Pending", + "Validated" + ], + "numberOfBytes": "1" + }, + "t_enum(Status)14785": { + "label": "enum TalentLayerService.Status", + "members": [ + "Opened", + "Confirmed", + "Finished", + "Cancelled", + "Uncompleted" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(AllowedToken)14829_storage)": { + "label": "mapping(address => struct TalentLayerService.AllowedToken)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_struct(RoleData)58_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_uint256,t_struct(Proposal)14824_storage))": { + "label": "mapping(uint256 => mapping(uint256 => struct TalentLayerService.Proposal))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Proposal)14824_storage)": { + "label": "mapping(uint256 => struct TalentLayerService.Proposal)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Service)14806_storage)": { + "label": "mapping(uint256 => struct TalentLayerService.Service)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_uint256)": { + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(AllowedToken)14829_storage": { + "label": "struct TalentLayerService.AllowedToken", + "members": [ + { + "label": "isWhitelisted", + "type": "t_bool", + "offset": 0, + "slot": "0" + }, + { + "label": "minimumTransactionAmount", + "type": "t_uint256", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Proposal)14824_storage": { + "label": "struct TalentLayerService.Proposal", + "members": [ + { + "label": "status", + "type": "t_enum(ProposalStatus)14788", + "offset": 0, + "slot": "0" + }, + { + "label": "ownerId", + "type": "t_uint256", + "offset": 0, + "slot": "1" + }, + { + "label": "rateToken", + "type": "t_address", + "offset": 0, + "slot": "2" + }, + { + "label": "rateAmount", + "type": "t_uint256", + "offset": 0, + "slot": "3" + }, + { + "label": "platformId", + "type": "t_uint256", + "offset": 0, + "slot": "4" + }, + { + "label": "dataUri", + "type": "t_string_storage", + "offset": 0, + "slot": "5" + }, + { + "label": "expirationDate", + "type": "t_uint256", + "offset": 0, + "slot": "6" + }, + { + "label": "referrerId", + "type": "t_uint256", + "offset": 0, + "slot": "7" + } + ], + "numberOfBytes": "256" + }, + "t_struct(RoleData)58_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)", + "offset": 0, + "slot": "0" + }, + { + "label": "adminRole", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Service)14806_storage": { + "label": "struct TalentLayerService.Service", + "members": [ + { + "label": "status", + "type": "t_enum(Status)14785", + "offset": 0, + "slot": "0" + }, + { + "label": "ownerId", + "type": "t_uint256", + "offset": 0, + "slot": "1" + }, + { + "label": "acceptedProposalId", + "type": "t_uint256", + "offset": 0, + "slot": "2" + }, + { + "label": "dataUri", + "type": "t_string_storage", + "offset": 0, + "slot": "3" + }, + { + "label": "transactionId", + "type": "t_uint256", + "offset": 0, + "slot": "4" + }, + { + "label": "platformId", + "type": "t_uint256", + "offset": 0, + "slot": "5" + }, + { + "label": "rateToken", + "type": "t_address", + "offset": 0, + "slot": "6" + }, + { + "label": "referralAmount", + "type": "t_uint256", + "offset": 0, + "slot": "7" + } + ], + "numberOfBytes": "256" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "2a12ac0fce1d139ca3c34a8d201fa199c7657f3adb52ca26ae5fcff7019db3b7": { + "address": "0xc7db42815412e7c5d1E8Ed057Bf8D8Ee2F55e25d", + "txHash": "0xbfa32de0c10cc735435e6efc0dc9bbe95996726210c71ce7e1f22da1725a94ba", + "layout": { + "solcVersion": "0.8.17", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\utils\\ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:94" + }, + { + "label": "_trustedForwarders", + "offset": 0, + "slot": "101", + "type": "t_mapping(t_address,t_bool)", + "contract": "ERC2771RecipientUpgradeable", + "src": "contracts\\libs\\ERC2771RecipientUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC165Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\utils\\introspection\\ERC165Upgradeable.sol:41" + }, + { + "label": "_name", + "offset": 0, + "slot": "152", + "type": "t_string_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:25" + }, + { + "label": "_symbol", + "offset": 0, + "slot": "153", + "type": "t_string_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:28" + }, + { + "label": "_owners", + "offset": 0, + "slot": "154", + "type": "t_mapping(t_uint256,t_address)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:31" + }, + { + "label": "_balances", + "offset": 0, + "slot": "155", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:34" + }, + { + "label": "_tokenApprovals", + "offset": 0, + "slot": "156", + "type": "t_mapping(t_uint256,t_address)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:37" + }, + { + "label": "_operatorApprovals", + "offset": 0, + "slot": "157", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:40" + }, + { + "label": "__gap", + "offset": 0, + "slot": "158", + "type": "t_array(t_uint256)44_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\token\\ERC721\\ERC721Upgradeable.sol:514" + }, + { + "label": "__gap", + "offset": 0, + "slot": "202", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\ERC1967\\ERC1967UpgradeUpgradeable.sol:211" + }, + { + "label": "__gap", + "offset": 0, + "slot": "252", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\UUPSUpgradeable.sol:107" + }, + { + "label": "nextReviewId", + "offset": 0, + "slot": "302", + "type": "t_struct(Counter)3290_storage", + "contract": "TalentLayerReview", + "src": "contracts\\TalentLayerReview.sol:47" + }, + { + "label": "reviews", + "offset": 0, + "slot": "303", + "type": "t_mapping(t_uint256,t_struct(Review)14307_storage)", + "contract": "TalentLayerReview", + "src": "contracts\\TalentLayerReview.sol:52" + }, + { + "label": "hasBuyerBeenReviewed", + "offset": 0, + "slot": "304", + "type": "t_mapping(t_uint256,t_bool)", + "contract": "TalentLayerReview", + "src": "contracts\\TalentLayerReview.sol:57" + }, + { + "label": "hasSellerBeenReviewed", + "offset": 0, + "slot": "305", + "type": "t_mapping(t_uint256,t_bool)", + "contract": "TalentLayerReview", + "src": "contracts\\TalentLayerReview.sol:62" + }, + { + "label": "tlId", + "offset": 0, + "slot": "306", + "type": "t_contract(ITalentLayerID)22004", + "contract": "TalentLayerReview", + "src": "contracts\\TalentLayerReview.sol:67" + }, + { + "label": "talentLayerService", + "offset": 0, + "slot": "307", + "type": "t_contract(ITalentLayerService)22448", + "contract": "TalentLayerReview", + "src": "contracts\\TalentLayerReview.sol:72" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)44_storage": { + "label": "uint256[44]", + "numberOfBytes": "1408" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(ITalentLayerID)22004": { + "label": "contract ITalentLayerID", + "numberOfBytes": "20" + }, + "t_contract(ITalentLayerService)22448": { + "label": "contract ITalentLayerService", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_address)": { + "label": "mapping(uint256 => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_bool)": { + "label": "mapping(uint256 => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Review)14307_storage)": { + "label": "mapping(uint256 => struct TalentLayerReview.Review)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Counter)3290_storage": { + "label": "struct CountersUpgradeable.Counter", + "members": [ + { + "label": "_value", + "type": "t_uint256", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(Review)14307_storage": { + "label": "struct TalentLayerReview.Review", + "members": [ + { + "label": "id", + "type": "t_uint256", + "offset": 0, + "slot": "0" + }, + { + "label": "ownerId", + "type": "t_uint256", + "offset": 0, + "slot": "1" + }, + { + "label": "dataUri", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "serviceId", + "type": "t_uint256", + "offset": 0, + "slot": "3" + }, + { + "label": "rating", + "type": "t_uint256", + "offset": 0, + "slot": "4" + } + ], + "numberOfBytes": "160" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "9e2b0eada60680f506ea93bebcf255a7d11503e12154d1968434159e21ffff13": { + "address": "0x9F4ab41bb4498B7B92bff27a859ed322E7Af82AB", + "txHash": "0x5f0a82f5ab2aee6b4a6110d11bc9efcda19de89e569fc1ef454d502f2db13873", + "layout": { + "solcVersion": "0.8.17", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\utils\\ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:94" + }, + { + "label": "_trustedForwarders", + "offset": 0, + "slot": "101", + "type": "t_mapping(t_address,t_bool)", + "contract": "ERC2771RecipientUpgradeable", + "src": "contracts\\libs\\ERC2771RecipientUpgradeable.sol:29" + }, + { + "label": "_paused", + "offset": 0, + "slot": "102", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\security\\PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "103", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\security\\PausableUpgradeable.sol:116" + }, + { + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC1967UpgradeUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\ERC1967\\ERC1967UpgradeUpgradeable.sol:211" + }, + { + "label": "__gap", + "offset": 0, + "slot": "202", + "type": "t_array(t_uint256)50_storage", + "contract": "UUPSUpgradeable", + "src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\UUPSUpgradeable.sol:107" + }, + { + "label": "transactions", + "offset": 0, + "slot": "252", + "type": "t_mapping(t_uint256,t_struct(Transaction)9282_storage)", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:282" + }, + { + "label": "platformIdToTokenToBalance", + "offset": 0, + "slot": "253", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:291" + }, + { + "label": "talentLayerServiceContract", + "offset": 0, + "slot": "254", + "type": "t_contract(ITalentLayerService)22448", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:296" + }, + { + "label": "talentLayerIdContract", + "offset": 0, + "slot": "255", + "type": "t_contract(ITalentLayerID)22004", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:301" + }, + { + "label": "talentLayerPlatformIdContract", + "offset": 0, + "slot": "256", + "type": "t_contract(ITalentLayerPlatformID)22226", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:306" + }, + { + "label": "protocolWallet", + "offset": 0, + "slot": "257", + "type": "t_address_payable", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:311" + }, + { + "label": "protocolEscrowFeeRate", + "offset": 20, + "slot": "257", + "type": "t_uint16", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:316" + }, + { + "label": "disputeIDtoTransactionID", + "offset": 0, + "slot": "258", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:346" + }, + { + "label": "nextTransactionId", + "offset": 0, + "slot": "259", + "type": "t_struct(Counter)3290_storage", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:351" + }, + { + "label": "referrerIdToTokenToBalance", + "offset": 0, + "slot": "260", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", + "contract": "TalentLayerEscrow", + "src": "contracts\\TalentLayerEscrow.sol:359" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_address_payable": { + "label": "address payable", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes_storage": { + "label": "bytes", + "numberOfBytes": "32" + }, + "t_contract(Arbitrator)7789": { + "label": "contract Arbitrator", + "numberOfBytes": "20" + }, + "t_contract(ITalentLayerID)22004": { + "label": "contract ITalentLayerID", + "numberOfBytes": "20" + }, + "t_contract(ITalentLayerPlatformID)22226": { + "label": "contract ITalentLayerPlatformID", + "numberOfBytes": "20" + }, + "t_contract(ITalentLayerService)22448": { + "label": "contract ITalentLayerService", + "numberOfBytes": "20" + }, + "t_enum(Status)9235": { + "label": "enum TalentLayerEscrow.Status", + "members": [ + "NoDispute", + "WaitingSender", + "WaitingReceiver", + "DisputeCreated", + "Resolved" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Transaction)9282_storage)": { + "label": "mapping(uint256 => struct TalentLayerEscrow.Transaction)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_uint256)": { + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32" + }, + "t_struct(Counter)3290_storage": { + "label": "struct CountersUpgradeable.Counter", + "members": [ + { + "label": "_value", + "type": "t_uint256", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(Transaction)9282_storage": { + "label": "struct TalentLayerEscrow.Transaction", + "members": [ + { + "label": "id", + "type": "t_uint256", + "offset": 0, + "slot": "0" + }, + { + "label": "sender", + "type": "t_address", + "offset": 0, + "slot": "1" + }, + { + "label": "receiver", + "type": "t_address", + "offset": 0, + "slot": "2" + }, + { + "label": "token", + "type": "t_address", + "offset": 0, + "slot": "3" + }, + { + "label": "amount", + "type": "t_uint256", + "offset": 0, + "slot": "4" + }, + { + "label": "releasedAmount", + "type": "t_uint256", + "offset": 0, + "slot": "5" + }, + { + "label": "serviceId", + "type": "t_uint256", + "offset": 0, + "slot": "6" + }, + { + "label": "proposalId", + "type": "t_uint256", + "offset": 0, + "slot": "7" + }, + { + "label": "protocolEscrowFeeRate", + "type": "t_uint16", + "offset": 0, + "slot": "8" + }, + { + "label": "originServiceFeeRate", + "type": "t_uint16", + "offset": 2, + "slot": "8" + }, + { + "label": "originValidatedProposalFeeRate", + "type": "t_uint16", + "offset": 4, + "slot": "8" + }, + { + "label": "arbitrator", + "type": "t_contract(Arbitrator)7789", + "offset": 6, + "slot": "8" + }, + { + "label": "status", + "type": "t_enum(Status)9235", + "offset": 26, + "slot": "8" + }, + { + "label": "disputeId", + "type": "t_uint256", + "offset": 0, + "slot": "9" + }, + { + "label": "senderFee", + "type": "t_uint256", + "offset": 0, + "slot": "10" + }, + { + "label": "receiverFee", + "type": "t_uint256", + "offset": 0, + "slot": "11" + }, + { + "label": "lastInteraction", + "type": "t_uint256", + "offset": 0, + "slot": "12" + }, + { + "label": "arbitratorExtraData", + "type": "t_bytes_storage", + "offset": 0, + "slot": "13" + }, + { + "label": "arbitrationFeeTimeout", + "type": "t_uint256", + "offset": 0, + "slot": "14" + }, + { + "label": "referrerId", + "type": "t_uint256", + "offset": 0, + "slot": "15" + }, + { + "label": "referralAmount", + "type": "t_uint256", + "offset": 0, + "slot": "16" + }, + { + "label": "totalAmount", + "type": "t_uint256", + "offset": 0, + "slot": "17" + } + ], + "numberOfBytes": "576" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" }, "t_uint256": { "label": "uint256", diff --git a/contracts/TalentLayerService.sol b/contracts/TalentLayerService.sol index 259cf1ca..7fb880fb 100644 --- a/contracts/TalentLayerService.sol +++ b/contracts/TalentLayerService.sol @@ -121,10 +121,9 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @notice Emit when data is updated for a Service * @param id The service ID * @param dataUri New service Data URI - * @param rateToken token address to be used for the service's payments * @param referralAmount New referral amount */ - event ServiceUpdated(uint256 id, string dataUri, address rateToken, uint256 referralAmount); + event ServiceUpdated(uint256 id, string dataUri, uint256 referralAmount); /** * @notice Emitted after a new proposal is created @@ -354,14 +353,12 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU * @notice Update Service URI data * @param _profileId The TalentLayer ID of the user, owner of the service * @param _serviceId, Service ID to update - * @param _rateToken token address to be used for the service's payments * @param _referralAmount, New referral amount * @param _dataUri New IPFS URI */ function updateService( uint256 _profileId, uint256 _serviceId, - address _rateToken, uint256 _referralAmount, string calldata _dataUri ) public onlyOwnerOrDelegate(_profileId) { @@ -369,14 +366,12 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU require(service.ownerId == _profileId, "Not the owner"); require(service.status == Status.Opened, "status must be opened"); require(bytes(_dataUri).length == 46, "Invalid cid"); - require(allowedTokenList[_rateToken].isWhitelisted, "Token not allowed"); require(_referralAmount >= service.referralAmount, "Can't reduce referral amount"); service.dataUri = _dataUri; service.referralAmount = _referralAmount; - service.rateToken = _rateToken; - emit ServiceUpdated(_serviceId, _dataUri, _rateToken, _referralAmount); + emit ServiceUpdated(_serviceId, _dataUri, _referralAmount); } /** diff --git a/scripts/playground/2-update-service.ts b/scripts/playground/2-update-service.ts index ea307d1d..8bc1912c 100644 --- a/scripts/playground/2-update-service.ts +++ b/scripts/playground/2-update-service.ts @@ -50,7 +50,7 @@ async function main() { await talentLayerService .connect(alice) - .updateService(aliceTlId, firstServiceId, ethers.constants.AddressZero, referralAmount, aliceUpdateJobData) + .updateService(aliceTlId, firstServiceId, referralAmount, aliceUpdateJobData) const jobDataAfterUpdate = await talentLayerService.getService(firstServiceId) console.log('Job Data after update', jobDataAfterUpdate) } diff --git a/test/batch/delegationSystem.ts b/test/batch/delegationSystem.ts index 38504ee1..4d988ab9 100644 --- a/test/batch/delegationSystem.ts +++ b/test/batch/delegationSystem.ts @@ -144,7 +144,7 @@ describe('Delegation System', function () { }) it('Dave can update service data on behalf of Alice', async function () { - const tx = await talentLayerService.connect(dave).updateService(aliceTlId, serviceId, ethers.constants.AddressZero, referralAmount, cid) + const tx = await talentLayerService.connect(dave).updateService(aliceTlId, serviceId, referralAmount, cid) await expect(tx).to.not.be.reverted }) diff --git a/test/batch/fullWorkflow.ts b/test/batch/fullWorkflow.ts index 59ce2ac3..713da902 100644 --- a/test/batch/fullWorkflow.ts +++ b/test/batch/fullWorkflow.ts @@ -931,29 +931,25 @@ describe('TalentLayer protocol global testing', function () { }) it('Alice can update her service data', async function () { - await talentLayerService.connect(alice).updateService(aliceTlId, 1, ethers.constants.AddressZero, referralAmount, cid2) + await talentLayerService.connect(alice).updateService(aliceTlId, 1, referralAmount, cid2) const serviceData = await talentLayerService.services(1) expect(serviceData.dataUri).to.be.equal(cid2) - expect(serviceData.rateToken).to.be.equal(ethers.constants.AddressZero) - // Revert update - await talentLayerService.connect(alice).updateService(aliceTlId, 1, token.address, referralAmount, cid2) - const newReferralAmount = 40000 const tx = await talentLayerService .connect(alice) - .updateService(aliceTlId, 6, ethers.constants.AddressZero, newReferralAmount, cid2) + .updateService(aliceTlId, 6, newReferralAmount, cid2) const service6Data = await talentLayerService.services(6) expect(tx) .to.emit(talentLayerService, 'ServiceUpdated') - .withArgs(6, cid2, ethers.constants.AddressZero, newReferralAmount) + .withArgs(6, cid2, newReferralAmount) expect(service6Data.referralAmount).to.be.equal(newReferralAmount) }) it('Alice cannot update her service with an inferior referral amount', async function () { await expect( - talentLayerService.connect(alice).updateService(aliceTlId, 1, token.address, referralAmount - 1, cid2), + talentLayerService.connect(alice).updateService(aliceTlId, 1, referralAmount - 1, cid2), ).to.be.revertedWith("Can't reduce referral amount") }) @@ -1541,7 +1537,7 @@ describe('TalentLayer protocol global testing', function () { it('Alice cannot update her service data after it is confirmed', async function () { const tx = talentLayerService .connect(alice) - .updateService(aliceTlId, serviceId, ethers.constants.AddressZero, referralAmount, cid2) + .updateService(aliceTlId, serviceId, referralAmount, cid2) await expect(tx).to.be.revertedWith('status must be opened') }) From ba0c363373d6dc3a10087edc519e0c1c51c19d90 Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Sat, 2 Dec 2023 12:22:18 +0000 Subject: [PATCH 98/99] Added optimizations to Service variable calls --- contracts/TalentLayerService.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/TalentLayerService.sol b/contracts/TalentLayerService.sol index 7fb880fb..09af1161 100644 --- a/contracts/TalentLayerService.sol +++ b/contracts/TalentLayerService.sol @@ -395,7 +395,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU bytes calldata _signature, uint256 _referrerId ) public payable onlyOwnerOrDelegate(_profileId) { - Service storage service = services[_serviceId]; + Service memory service = services[_serviceId]; _validateProposal(_profileId, _serviceId, _rateAmount, _platformId, _dataUri, _signature, _referrerId); proposals[_serviceId][_profileId] = Proposal({ @@ -624,7 +624,7 @@ contract TalentLayerService is Initializable, ERC2771RecipientUpgradeable, UUPSU uint256 proposalPostingFee = talentLayerPlatformIdContract.getProposalPostingFee(_platformId); require(msg.value == proposalPostingFee, "Non-matching funds"); - Service storage service = services[_serviceId]; + Service memory service = services[_serviceId]; require( _rateAmount + service.referralAmount >= allowedTokenList[service.rateToken].minimumTransactionAmount, "Amount too low" From 51bd6764a3924bc435eeadd50a0880f23b4d12ef Mon Sep 17 00:00:00 2001 From: "Quentin D.C" Date: Sun, 3 Dec 2023 12:41:01 +0000 Subject: [PATCH 99/99] Fixed error --- scripts/tasks/protocol/add-trusted-forwarder.ts | 2 +- scripts/tasks/protocol/remove-trusted-forwarder.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/tasks/protocol/add-trusted-forwarder.ts b/scripts/tasks/protocol/add-trusted-forwarder.ts index 56b1c4f0..2db382e6 100644 --- a/scripts/tasks/protocol/add-trusted-forwarder.ts +++ b/scripts/tasks/protocol/add-trusted-forwarder.ts @@ -27,7 +27,7 @@ task('add-trusted-forwarder', 'Adds a trusted forwarder for meta transactions.') const talentLayerReview = await ethers.getContractAt( 'TalentLayerReview', - getDeploymentProperty(network.name, DeploymentProperty.Reviewscontract), + getDeploymentProperty(network.name, DeploymentProperty.TalentLayerReview), ) const talentLayerEscrow = await ethers.getContractAt( diff --git a/scripts/tasks/protocol/remove-trusted-forwarder.ts b/scripts/tasks/protocol/remove-trusted-forwarder.ts index e52cf5c1..c04a5fae 100644 --- a/scripts/tasks/protocol/remove-trusted-forwarder.ts +++ b/scripts/tasks/protocol/remove-trusted-forwarder.ts @@ -26,7 +26,7 @@ task('remove-trusted-forwarder', 'Removes a trusted forwarder for meta transacti const talentLayerReview = await ethers.getContractAt( 'TalentLayerReview', - getDeploymentProperty(network.name, DeploymentProperty.Reviewscontract), + getDeploymentProperty(network.name, DeploymentProperty.TalentLayerReview), ) const talentLayerEscrow = await ethers.getContractAt(