// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; import "./IERC20RewardDistributor.sol"; import "../../contract-registry/ContractEntity.sol"; import "../../contract-registry/Contracts.sol"; import "../../acl/direct/AccessControlledUpgradeable.sol"; import "./ERC20RewardDistributorStorage.sol"; import "./ERC20RewardDistributionHelper.sol"; import "../../listing/listing-manager/IListingManager.sol"; import "../../renting/renting-manager/IRentingManager.sol"; contract ERC20RewardDistributor is IERC20RewardDistributor, UUPSUpgradeable, ContractEntity, AccessControlledUpgradeable, ERC20RewardDistributorStorage { using SafeERC20Upgradeable for IERC20Upgradeable; /** * @dev ERC20RewardDistributor initialization params. * @param acl ACL contract address. * @param metahub Metahub contract address. */ struct ERC20RewardDistributorInitParams { IACL acl; IMetahub metahub; } /** * @dev Constructor that gets called for the implementation contract. * @custom:oz-upgrades-unsafe-allow constructor */ constructor() { _disableInitializers(); } function initialize(ERC20RewardDistributorInitParams calldata params) external initializer { __UUPSUpgradeable_init(); _aclContract = IACL(params.acl); _metahub = IMetahub(params.metahub); } /// @inheritdoc IERC20RewardDistributor function distributeExternalReward( uint256 agreementId, address token, uint256 rewardAmount ) external returns (Accounts.RentalEarnings memory rentalExternalRewardEarnings) { Rentings.Agreement memory agreement = IRentingManager(_metahub.getContract(Contracts.RENTING_MANAGER)) .rentalAgreementInfo(agreementId); ERC20RewardDistributionHelper.RentalExternalERC20RewardFees memory rentalExternalERC20RewardFees = ERC20RewardDistributionHelper.getRentalExternalERC20RewardFees( agreement, token, rewardAmount ); if (rentalExternalERC20RewardFees.totalReward > 0) { IERC20Upgradeable(token).safeIncreaseAllowance( address(_metahub), rentalExternalERC20RewardFees.totalReward ); Listings.Listing memory listing = IListingManager(_metahub.getContract(Contracts.LISTING_MANAGER)) .listingInfo(agreement.listingId); rentalExternalRewardEarnings = IMetahub(_metahub).handleExternalERC20Reward( listing, agreement, rentalExternalERC20RewardFees ); } } /** * @inheritdoc IContractEntity */ function contractKey() external pure override returns (bytes4) { return Contracts.ERC20_REWARD_DISTRIBUTOR; } /** * @inheritdoc IERC165 */ function supportsInterface(bytes4 interfaceId) public view override(ContractEntity, IERC165) returns (bool) { return interfaceId == type(IERC20RewardDistributor).interfaceId || super.supportsInterface(interfaceId); } /** * @inheritdoc UUPSUpgradeable */ function _authorizeUpgrade(address newImplementation) internal override onlyAdmin { // solhint-disable-previous-line no-empty-blocks } /** * @inheritdoc AccessControlledUpgradeable */ function _acl() internal view override returns (IACL) { return _aclContract; } }