* @notice Distribute token to winners according to the percentages
* @dev Only factory contract can call this function
* @param token The token address to distribute
* @param winners The addresses array of winners
* @param percentages The percentages array of winners
*/
function distribute(address token, address[] memory winners, uint256[] memory percentages, bytes memory data)
external
{
if (msg.sender != FACTORY_ADDRESS) {
revert Distributor__OnlyFactoryAddressIsAllowed();
}
_distribute(token, winners, percentages, data);
}
* @notice An internal function to distribute JPYC to winners
* @dev Main logic of distribution is implemented here. The length of winners and percentages must be the same
* The token address must be one of the whitelisted tokens
* The winners and percentages array are supposed not to be so long, so the loop can stay unbounded
* The total percentage must be correct. It must be (100 - COMMITION_FEE).
* Finally send the remained token(fee) to STADIUM_ADDRESS with no dust in the contract
* @param token The token address
* @param winners The addresses of winners
* @param percentages The percentages of winners
* @param data The data to be logged. It is supposed to be used for showing the realation bbetween winners and proposals.
*/
function _distribute(address token, address[] memory winners, uint256[] memory percentages, bytes memory data)
internal
{
if (token == address(0)) revert Distributor__NoZeroAddress();
if (!_isWhiteListed(token)) {
revert Distributor__InvalidTokenAddress();
}
if (winners.length == 0 || winners.length != percentages.length) revert Distributor__MismatchedArrays();
uint256 percentagesLength = percentages.length;
uint256 totalPercentage;
for (uint256 i; i < percentagesLength;) {
totalPercentage += percentages[i];
unchecked {
++i;
}
}
if (totalPercentage != (10000 - COMMISSION_FEE)) {
revert Distributor__MismatchedPercentages();
}
IERC20 erc20 = IERC20(token);
uint256 totalAmount = erc20.balanceOf(address(this));
if (totalAmount == 0) revert Distributor__NoTokenToDistribute();
uint256 winnersLength = winners.length;
for (uint256 i; i < winnersLength;) {
uint256 amount = totalAmount * percentages[i] / BASIS_POINTS;
erc20.safeTransfer(winners[i], amount);
unchecked {
++i;
}
}
_commissionTransfer(erc20);
emit Distributed(token, winners, percentages, data);
}