Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

335 referral system #197

Open
wants to merge 100 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 89 commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
ed6d77d
First draft on TalentLayerServiceV2.sol
quent043 May 30, 2023
8ad8fda
First draft on TalentLayerEscrowV2.sol
quent043 May 30, 2023
25d5f65
Added new functions in TalentLayerServiceV2.sol
quent043 May 31, 2023
a71195c
Added new functions in TalentLayerServiceV2.sol
quent043 May 31, 2023
1683046
Removed fields from tests
quent043 May 31, 2023
7407a52
Updated updateService function
quent043 May 31, 2023
d083d9c
Updated tests
quent043 May 31, 2023
b630bc5
Updated delegation tests
quent043 May 31, 2023
f3bfa51
Updated audit tests
quent043 May 31, 2023
d72be64
Updated load tests
quent043 May 31, 2023
fe78b13
Updated platform verification tests
quent043 May 31, 2023
4e3e1c6
Updated pausable escrow verification tests
quent043 May 31, 2023
2265b07
Updated delegation tests
quent043 May 31, 2023
e5ae868
Revers commit on original contracts
quent043 May 31, 2023
035a392
Updated serviceCompletion.ts tests
quent043 Jun 1, 2023
338c460
Updated disputeResolution.ts tests
quent043 Jun 1, 2023
f52e7e5
Added tests for new functions.
quent043 Jun 5, 2023
5f4aab5
Added an event
quent043 Jun 5, 2023
f9a6de8
Updated tests with events emissions
quent043 Jun 5, 2023
14c6fee
Added missing assertions + event assertions
quent043 Jun 5, 2023
d8d6f0c
Fixed nat spec
quent043 Jun 5, 2023
68e8c23
Added indexed in event
quent043 Jun 6, 2023
b37c9c7
Refactored Contract upgrades naming & organization
quent043 Jun 6, 2023
6ca051f
Refactored tests to fit new naming
quent043 Jun 6, 2023
e02ba9d
Added new function to TalentLayerService.sol contract
quent043 Jun 8, 2023
6133da9
Updated tests
quent043 Jun 8, 2023
cc3e7ed
Renamed contract variable
quent043 Jun 8, 2023
392fa20
Added new test for new function
quent043 Jun 8, 2023
7ed97d8
Added id check
quent043 Jun 8, 2023
cb39a5b
Added id check tests
quent043 Jun 8, 2023
56d642f
Removed rateToken from service metadata
quent043 Jun 9, 2023
4cab0d9
Added 2 new fields to Transaction
quent043 Jun 9, 2023
a26caaf
Added referralAmount in fees calculations
quent043 Jun 9, 2023
7a4ba1c
Added referralAmount in fees distribution
quent043 Jun 9, 2023
176369d
Added test on new fee calculation
quent043 Jun 9, 2023
a8a243a
Fixed arythmetic bug
quent043 Jun 9, 2023
ef36da3
Gas saving
quent043 Jun 9, 2023
fda6026
Added test 1 for referral release using ETH
quent043 Jun 9, 2023
d5291d9
Modified Escrow transfer function for referral amount
quent043 Jun 9, 2023
754725e
Added tests for release function using ERC20 & ETH
quent043 Jun 9, 2023
ecefa0c
Had to add "uint256 totalAmount" field
quent043 Jun 9, 2023
a7cf324
Remove only
quent043 Jun 9, 2023
1110ae3
Reworded
quent043 Jun 9, 2023
882461b
Recatored variables order in Transaction struct
quent043 Jun 12, 2023
2473716
Updated escrow interface
quent043 Jun 12, 2023
88049a8
Update ReferralAmountReleased event
quent043 Jun 12, 2023
8015bb8
Updated Service Interface
quent043 Jun 13, 2023
dd0d1a7
Refactored Escrow contract: last version
quent043 Jun 13, 2023
21543e7
Small gas optimization
quent043 Jun 13, 2023
1fe877b
Added require statement + 2 pending features
quent043 Jun 13, 2023
95ce758
Modified comments
quent043 Jun 14, 2023
7494ba1
Removed createServiceWithReferral function & event
quent043 Jun 14, 2023
6906e6f
Updated tests
quent043 Jun 14, 2023
3b36de5
Removed token from service update
quent043 Jun 14, 2023
c4bb785
Updated tests
quent043 Jun 14, 2023
f805f95
Removed createProposalWithReferrer
quent043 Jun 14, 2023
9330f92
Updated tests
quent043 Jun 14, 2023
d499ac5
Removed comment
quent043 Jun 14, 2023
04ad7a5
Renamed variables, removed "rate"
quent043 Jun 14, 2023
0f95e33
Updated tests
quent043 Jun 14, 2023
02de40f
Created archive interfaces
quent043 Jun 14, 2023
5c1d36c
Refactored into ternary
quent043 Jun 14, 2023
de4a60d
Quick refacto
quent043 Jun 14, 2023
6a68d11
Added referrerBalance mapping instead of transferring balance directl…
quent043 Jun 14, 2023
064ff85
Updated tests
quent043 Jun 14, 2023
5cee3ca
Fixed variable mistake
quent043 Jun 14, 2023
d2adcbd
Added 2 require statements
quent043 Jun 15, 2023
7d6a409
Updated tests
quent043 Jun 15, 2023
b750fbf
Rename variables with "rate" (could not upgrade)
quent043 Jun 15, 2023
0b5a479
Update tests
quent043 Jun 15, 2023
dca9904
Moved new mapping to bottom of variables sections
quent043 Jun 15, 2023
688858a
Modified new events names
quent043 Jun 15, 2023
30b3254
Moved a function in Service contract
quent043 Jun 16, 2023
ba62899
Fixed a bug in escrow contract
quent043 Jun 16, 2023
f21c3b2
Update Service Interface
quent043 Jun 16, 2023
e1c5143
Update Escrow Interface
quent043 Jun 16, 2023
8805587
Renamed events
quent043 Jun 16, 2023
a74368d
Updated tests with correct tests + args
quent043 Jun 16, 2023
a3e49af
Removed isValid check for referral balance view
quent043 Jun 20, 2023
4d60193
amount => rateAmount
quent043 Jun 20, 2023
8263d23
Remove require statement
quent043 Jun 20, 2023
6c2113c
Added deploy script for V1 upgrade test
quent043 Jun 20, 2023
fd2022c
First draft on V1 migration test
quent043 Jun 20, 2023
7f9bd58
Added tests on services 1 & 2
quent043 Jun 20, 2023
31010fc
Added tests on services 3
quent043 Jun 20, 2023
05a458c
Revert address update
quent043 Jun 20, 2023
7f94981
Finalized referral upgrade tests
quent043 Jun 20, 2023
f25d1b5
Final check on Escrow NatSpec
quent043 Jun 20, 2023
f4d13f0
Final check on Service NatSpec
quent043 Jun 20, 2023
5fed205
Updated Escrow contract to modify fee calculation
quent043 Jul 26, 2023
118fa86
Updated tests
quent043 Jul 26, 2023
8f90926
Reverted changes in json files
quent043 Jul 28, 2023
7f84e7a
Update Natspec
quent043 Jul 28, 2023
cf3b865
Merge main
quent043 Nov 26, 2023
0de07fc
Added missing + !
quent043 Nov 30, 2023
be86269
Updated updateService function
quent043 Dec 1, 2023
fcd1153
Updated Playground
quent043 Dec 1, 2023
797bd99
Reverted updateService change
quent043 Dec 1, 2023
ba0c363
Added optimizations to Service variable calls
quent043 Dec 2, 2023
51bd676
Fixed error
quent043 Dec 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3,146 changes: 2,381 additions & 765 deletions .openzeppelin/polygon-mumbai.json

Large diffs are not rendered by default.

138 changes: 118 additions & 20 deletions contracts/TalentLayerEscrow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
* @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
Expand All @@ -88,6 +88,9 @@ 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 amount to be sent to the referrer
* @param totalAmount The amount of the transaction EXCLUDING FEES (fixed, will not vary)
*/
struct Transaction {
uint256 id;
Expand All @@ -109,6 +112,9 @@ contract TalentLayerEscrow is
uint256 lastInteraction;
bytes arbitratorExtraData;
uint256 arbitrationFeeTimeout;
uint256 referrerId;
uint256 referralAmount;
uint256 totalAmount;
}

// =========================== Events ==============================
Expand Down Expand Up @@ -149,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 TalentLayerID 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.
Expand Down Expand Up @@ -177,6 +191,20 @@ contract TalentLayerEscrow is
uint256 _amount
);

/**
* @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,
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.
Expand Down Expand Up @@ -320,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();
Expand Down Expand Up @@ -368,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) {
Expand All @@ -382,6 +418,15 @@ contract TalentLayerEscrow is
return platformIdToTokenToBalance[platformId][_token];
}

/**
* @param _token Token address (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());
return referrerIdToTokenToBalance[referrerId][_token];
}

/**
* @notice Called to get the details of a transaction
* @dev Only the transaction sender or receiver can call this function
Expand Down Expand Up @@ -442,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,
Expand All @@ -463,13 +508,16 @@ contract TalentLayerEscrow is
? talentLayerPlatformIdContract.getPlatform(proposal.platformId)
: originServiceCreationPlatform;

uint256 referralAmount = proposal.referrerId == 0 ? 0 : service.referralAmount;

uint256 transactionAmount = _calculateTotalWithFees(
proposal.rateAmount,
originServiceCreationPlatform.originServiceFeeRate,
originProposalCreationPlatform.originValidatedProposalFeeRate
originProposalCreationPlatform.originValidatedProposalFeeRate,
referralAmount
);

if (proposal.rateToken == address(0)) {
if (service.rateToken == address(0)) {
require(msg.value == transactionAmount, "Non-matching funds");
} else {
require(msg.value == 0, "Non-matching funds");
Expand All @@ -491,7 +539,8 @@ contract TalentLayerEscrow is
id: transactionId,
sender: sender,
receiver: receiver,
token: proposal.rateToken,
token: service.rateToken,
totalAmount: proposal.rateAmount,
amount: proposal.rateAmount,
releasedAmount: 0,
serviceId: _serviceId,
Expand All @@ -506,15 +555,17 @@ 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();

talentLayerServiceContract.afterDeposit(_serviceId, _proposalId, transactionId);

if (proposal.rateToken != address(0)) {
IERC20Upgradeable(proposal.rateToken).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);
Expand All @@ -525,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.
*/
Expand All @@ -546,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.
*/
Expand Down Expand Up @@ -729,6 +780,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).
* @dev Emits a BalanceTransferred & a ReferralAmountClaimed events
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BalanceTransferred ?

*/
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 ==============================

/**
Expand Down Expand Up @@ -841,10 +914,10 @@ 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 transavtion
* @param _transactionId The ID of the transaction
* @param _metaEvidence The meta evidence of the transaction
*/
function _afterCreateTransaction(
Expand Down Expand Up @@ -896,12 +969,21 @@ contract TalentLayerEscrow is
*/
function _reimburse(uint256 _transactionId, uint256 _amount) private {
Transaction storage transaction = transactions[_transactionId];
uint256 totalReleaseAmount = _calculateTotalWithFees(

// 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;

uint256 totalReimburseAmount = _calculateTotalWithFees(
_amount,
transaction.originServiceFeeRate,
transaction.originValidatedProposalFeeRate
transaction.originValidatedProposalFeeRate,
reimbursedReferralAmount
);
_safeTransferBalance(payable(transaction.sender), transaction.token, totalReleaseAmount);
_safeTransferBalance(payable(transaction.sender), transaction.token, totalReimburseAmount);

_afterPayment(_transactionId, PaymentType.Reimburse, _amount);
}
Expand Down Expand Up @@ -932,12 +1014,25 @@ contract TalentLayerEscrow is
transaction.token
] += originValidatedProposalFeeRate;

if (transaction.referrerId != 0 && transaction.referralAmount != 0) {
0xRomain marked this conversation as resolved.
Show resolved Hide resolved
uint256 releasedReferralAmount = (_releaseAmount * transaction.referralAmount) / (transaction.totalAmount);
referrerIdToTokenToBalance[transaction.referrerId][transaction.token] = releasedReferralAmount;

emit ReferralAmountReleased(
transaction.referrerId,
transaction.serviceId,
transaction.token,
releasedReferralAmount
);
}

emit OriginServiceFeeRateReleased(
originServiceCreationPlatformId,
transaction.serviceId,
transaction.token,
originServiceFeeRate
);

emit OriginValidatedProposalFeeRateReleased(
originValidatedProposalPlatformId,
transaction.serviceId,
Expand All @@ -947,7 +1042,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
Expand Down Expand Up @@ -1007,18 +1102,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 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(
uint256 _amount,
uint16 _originServiceFeeRate,
uint16 _originValidatedProposalFeeRate
uint16 _originValidatedProposalFeeRate,
uint256 _referralAmount
) private view returns (uint256 totalEscrowAmount) {
return
totalEscrowAmount =
_amount +
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just realize there is an issue here. The system can only work if we are taking the same fees that we do today on the _amount, for the _referralAmount. With fees it becomes sybil resistant
So here, _originServiceFeeRate, _originValidatedProposalFeeRate and _originValidatedProposalFeeRate should be applied to _referralAmount

(((_amount * protocolEscrowFeeRate) +
(_amount * _originServiceFeeRate) +
(_amount * _originValidatedProposalFeeRate)) / FEE_DIVIDER);
(_amount * _originValidatedProposalFeeRate)) / FEE_DIVIDER) +
_referralAmount;
}

// =========================== Overrides ==============================
Expand Down
Loading