Contract Name:
PhenixReferral
Contract Source Code:
File 1 of 1 : PhenixReferral
/**
*Submitted for verification at cronoscan.com on 2022-04-25
*/
// File: contracts/SafeMath.sol
// OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol)
pragma solidity ^0.8.0;
// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.
/**
* @dev Wrappers over Solidity's arithmetic operations.
*
* NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
* now has built in overflow checking.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b)
internal
pure
returns (bool, uint256)
{
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the substraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b)
internal
pure
returns (bool, uint256)
{
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b)
internal
pure
returns (bool, uint256)
{
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b)
internal
pure
returns (bool, uint256)
{
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b)
internal
pure
returns (bool, uint256)
{
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator.
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}
// File: contracts/Context.sol
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity >=0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
// File: contracts/Ownable.sol
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)
pragma solidity >=0.8.0;
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(
newOwner != address(0),
"Ownable: new owner is the zero address"
);
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
// File: contracts/IERC20.sol
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender)
external
view
returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}
// File: contracts/IUniswapV2Router01.sol
pragma solidity >=0.8.0;
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
)
external
returns (
uint256 amountA,
uint256 amountB,
uint256 liquidity
);
function addLiquidityETH(
address token,
uint256 amountTokenDesired,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
)
external
payable
returns (
uint256 amountToken,
uint256 amountETH,
uint256 liquidity
);
function removeLiquidity(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) external returns (uint256 amountA, uint256 amountB);
function removeLiquidityETH(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) external returns (uint256 amountToken, uint256 amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256 amountA, uint256 amountB);
function removeLiquidityETHWithPermit(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256 amountToken, uint256 amountETH);
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapTokensForExactTokens(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapExactETHForTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
function swapTokensForExactETH(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapExactTokensForETH(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapETHForExactTokens(
uint256 amountOut,
address[] calldata path,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
function quote(
uint256 amountA,
uint256 reserveA,
uint256 reserveB
) external pure returns (uint256 amountB);
function getAmountOut(
uint256 amountIn,
uint256 reserveIn,
uint256 reserveOut
) external pure returns (uint256 amountOut);
function getAmountIn(
uint256 amountOut,
uint256 reserveIn,
uint256 reserveOut
) external pure returns (uint256 amountIn);
function getAmountsOut(uint256 amountIn, address[] calldata path)
external
view
returns (uint256[] memory amounts);
function getAmountsIn(uint256 amountOut, address[] calldata path)
external
view
returns (uint256[] memory amounts);
}
// File: contracts/IUniswapV2Router02.sol
pragma solidity >=0.8.0;
interface IUniswapV2Router02 is IUniswapV2Router01 {
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) external returns (uint256 amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256 amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external;
}
// File: contracts/PhenixReferral.sol
pragma solidity >=0.8.0;
contract PhenixReferral is Ownable {
using SafeMath for uint256;
address public routerAddress;
address public tokenAddress;
uint256 public totalEthSwapped;
uint256 public totalEthRewards;
uint256 public totalPendingEthRewards;
uint256 public totalTokensSwapped;
bool public referralModeActive;
uint256 public minTokensRequired;
uint256 public totalReferralLevels;
uint256 public baseBuyAllocation;
uint256 public baseBuyAllocationDenomiator;
struct Referrer {
uint256 totalReferredEth;
uint256 totalReferredTokens;
uint256 totalReferredEthRewards;
uint256 pendingReferredEthRewards;
uint256 referrerLevel;
uint256 totalReferrals;
bool referralStatus;
}
struct ReferrerLevel {
uint256 referredEthRequirement;
uint256 referrerFeeAllocationPercentage;
uint256 feePercentageDenominator;
}
mapping(address => Referrer) private referrers;
address[] referrerAddresses;
mapping(uint256 => ReferrerLevel) referrerLevels;
mapping(address => mapping(address => bool)) public hasReferred;
modifier isEnabled() {
require(referralModeActive == true, "Referral Mode is not active.");
_;
}
modifier isJoined(address _referrerAddress) {
require(
referrers[_referrerAddress].referralStatus == true,
"Address is not in referral program."
);
_;
}
modifier canJoin() {
require(
IERC20(tokenAddress).balanceOf(msg.sender) >= minTokensRequired &&
referrers[msg.sender].referralStatus == false,
"Not enough tokens to join referral program or already in the referral program."
);
_;
}
modifier canClaim() {
require(
(referrers[msg.sender].pendingReferredEthRewards > 0) &&
(address(this).balance >=
referrers[msg.sender].pendingReferredEthRewards),
"No rewards to claim or not enough ETH in contract."
);
_;
}
modifier referralAllowed(address _referrerAddress) {
require(
_referrerAddress != msg.sender,
"Referrer and buyer cannot be the same."
);
_;
}
event UpdateReferralLevelFees(
uint256 _referralLevel,
uint256 _referredEthRequirement,
uint256 indexed _referrerFeeAllocationPercentage,
uint256 indexed _feePercentageDenominator
);
event SwapExactEthForTokensWithReferral(
address indexed _referrerAddress,
address indexed _buyerAddress,
uint256 indexed _amountEthSwapped
);
event ClaimEthRewards(
address indexed _referrerAddress,
uint256 indexed _claimedEthAmount
);
event UpdateReferralActiveState(bool indexed _state);
event JoinReferralProgram(address indexed _reffererAddress);
event UpdateMinimumTokensRequired(uint256 indexed _amountTokens);
event UpdateTokenAddress(address indexed _tokenAddress);
event UpdateRouterAddress(address indexed _routerAddress);
event UpdateBaseBuyAllocation(
uint256 indexed _percentage,
uint256 indexed _denominator
);
constructor(address _tokenAddress, address _routerAddress) {
tokenAddress = _tokenAddress;
routerAddress = _routerAddress;
referrers[msg.sender].referralStatus = true;
referrerAddresses.push(msg.sender);
_addReferralLevel(0, 1, 100);
_addReferralLevel(15000000000000000000000, 2, 100);
_addReferralLevel(50000000000000000000000, 3, 100);
_addReferralLevel(100000000000000000000000, 5, 100);
baseBuyAllocation = 88;
baseBuyAllocationDenomiator = 100;
referralModeActive = false;
}
function updateReferralActiveState(bool _state) external onlyOwner {
referralModeActive = _state;
emit UpdateReferralActiveState(_state);
}
function updateMinimumTokensRequired(uint256 _minTokens)
external
onlyOwner
{
minTokensRequired = _minTokens;
emit UpdateMinimumTokensRequired(_minTokens);
}
function updateBaseBuyAllocation(uint256 _percentage, uint256 _denominator)
external
onlyOwner
{
baseBuyAllocation = _percentage;
baseBuyAllocationDenomiator = _denominator;
emit UpdateBaseBuyAllocation(_percentage, _denominator);
}
function getTotalReferrers() external view returns(uint256) {
return referrerAddresses.length;
}
function joinReferralProgram() external canJoin {
referrers[msg.sender].referralStatus = true;
referrerAddresses.push(msg.sender);
emit JoinReferralProgram(msg.sender);
}
function getReferrerAddressByIndex(uint256 _index)
external
view
returns (address)
{
return referrerAddresses[_index];
}
function getReferrerDetails(address _address)
external
view
returns (
uint256,
uint256,
uint256,
uint256,
uint256,
uint256,
bool
)
{
return (
referrers[_address].totalReferredEth,
referrers[_address].totalReferredTokens,
referrers[_address].totalReferredEthRewards,
referrers[_address].pendingReferredEthRewards,
referrers[_address].referrerLevel,
referrers[_address].totalReferrals,
referrers[_address].referralStatus
);
}
function getReferralLevelDetails(uint256 _level)
external
view
returns (
uint256,
uint256,
uint256
)
{
return (
referrerLevels[_level].referredEthRequirement,
referrerLevels[_level].referrerFeeAllocationPercentage,
referrerLevels[_level].feePercentageDenominator
);
}
function _getReferrerLevelAndUpdate(
address _referrerAddress,
uint256 _payableValue
) internal returns (uint256) {
uint256 referrerLevel = referrers[_referrerAddress].referrerLevel;
uint256 newTotalReferredEth = referrers[_referrerAddress]
.totalReferredEth
.add(_payableValue);
// check if referrer needs to be upgraded to the next rank
if (referrerLevel != (totalReferralLevels - 1)) {
for (uint256 i = referrerLevel; i < totalReferralLevels; i++) {
if (
newTotalReferredEth >=
referrerLevels[i].referredEthRequirement
) {
referrerLevel = i;
}
}
}
// check if referrer level has updated then apply new level to data
if (referrerLevel != referrers[_referrerAddress].referrerLevel) {
referrers[_referrerAddress].referrerLevel = referrerLevel;
}
return referrers[_referrerAddress].referrerLevel;
}
function _getPathForETHtoToken() internal view returns (address[] memory) {
address[] memory path = new address[](2);
path[0] = IUniswapV2Router02(routerAddress).WETH();
path[1] = address(tokenAddress);
return path;
}
function updateTokenAddress(address _tokenAddress) external onlyOwner {
tokenAddress = _tokenAddress;
emit UpdateTokenAddress(_tokenAddress);
}
function updateRouterAddress(address _routerAddress) external onlyOwner {
routerAddress = _routerAddress;
emit UpdateRouterAddress(_routerAddress);
}
function swapExactEthForTokensWithReferral(
address _referrerAddress,
uint256 _deadline
)
external
payable
isJoined(_referrerAddress)
referralAllowed(_referrerAddress)
isEnabled
{
require(msg.value > 0, "No ETH payed in transaction.");
if (hasReferred[_referrerAddress][msg.sender] != true) {
hasReferred[_referrerAddress][msg.sender] = true;
referrers[_referrerAddress].totalReferrals = referrers[
_referrerAddress
].totalReferrals.add(1);
}
uint256 referrerLevel = _getReferrerLevelAndUpdate(
_referrerAddress,
msg.value
);
ReferrerLevel memory currentReferrerLevel = referrerLevels[
referrerLevel
];
// update referrer allocation and update payable amount to router
uint256 referrerFeeAllocation = uint256(msg.value)
.mul(currentReferrerLevel.referrerFeeAllocationPercentage)
.div(currentReferrerLevel.feePercentageDenominator);
// update referrer eth reward values
referrers[_referrerAddress].totalReferredEthRewards = referrers[
_referrerAddress
].totalReferredEthRewards.add(referrerFeeAllocation);
referrers[_referrerAddress].pendingReferredEthRewards = referrers[
_referrerAddress
].pendingReferredEthRewards.add(referrerFeeAllocation);
referrers[_referrerAddress].totalReferredEth = referrers[
_referrerAddress
].totalReferredEth.add(msg.value);
uint256 newPaybleAmount = uint256(msg.value).sub(referrerFeeAllocation);
uint256[] memory amounts = new uint256[](2);
uint256[] memory amountsFull = new uint256[](2);
amounts = IUniswapV2Router02(routerAddress).swapExactETHForTokens{
value: newPaybleAmount
}(0, _getPathForETHtoToken(), address(this), _deadline);
amountsFull = IUniswapV2Router02(routerAddress).getAmountsOut(
msg.value,
_getPathForETHtoToken()
);
referrers[_referrerAddress].totalReferredTokens = referrers[
_referrerAddress
].totalReferredTokens.add(amounts[1]);
uint256 buyerTokenAllocation = amountsFull[1]
.mul(baseBuyAllocation)
.div(baseBuyAllocationDenomiator);
// send buyer token allocation
IERC20(tokenAddress).transfer(msg.sender, buyerTokenAllocation);
// update globals
totalEthSwapped = totalEthSwapped.add(msg.value);
totalTokensSwapped = totalTokensSwapped.add(amounts[1]);
totalEthRewards = totalEthRewards.add(referrerFeeAllocation);
totalPendingEthRewards = totalPendingEthRewards.add(
referrerFeeAllocation
);
emit SwapExactEthForTokensWithReferral(
_referrerAddress,
msg.sender,
msg.value
);
}
function claimEthRewards() external isJoined(msg.sender) canClaim {
uint256 rewardsToClaim = referrers[msg.sender]
.pendingReferredEthRewards;
referrers[msg.sender].pendingReferredEthRewards = 0;
totalPendingEthRewards = totalPendingEthRewards.sub(rewardsToClaim);
(bool sent, ) = address(msg.sender).call{value: rewardsToClaim}("");
require(sent, "Claim failed.");
emit ClaimEthRewards(msg.sender, rewardsToClaim);
}
function updateReferralLevelFees(
uint256 _referralLevel,
uint256 _referredEthRequirement,
uint256 _referrerFeeAllocationPercentage,
uint256 _feePercentageDenominator
) external onlyOwner {
require(
_referralLevel <= totalReferralLevels,
"Referral level exceeds total referral levels"
);
referrerLevels[_referralLevel]
.referredEthRequirement = _referredEthRequirement;
referrerLevels[_referralLevel]
.referrerFeeAllocationPercentage = _referrerFeeAllocationPercentage;
referrerLevels[_referralLevel]
.feePercentageDenominator = _feePercentageDenominator;
emit UpdateReferralLevelFees(
_referralLevel,
_referredEthRequirement,
_referrerFeeAllocationPercentage,
_feePercentageDenominator
);
}
function _addReferralLevel(
uint256 _referredEthRequirement,
uint256 _referrerFeeAllocationPercentage,
uint256 _feePercentageDenominator
) internal {
referrerLevels[totalReferralLevels] = ReferrerLevel(
_referredEthRequirement,
_referrerFeeAllocationPercentage,
_feePercentageDenominator
);
totalReferralLevels = totalReferralLevels.add(1);
}
function addReferralLevel(
uint256 _referredEthRequirement,
uint256 _referrerFeeAllocationPercentage,
uint256 _feePercentageDenominator
) external onlyOwner {
_addReferralLevel(
_referredEthRequirement,
_referrerFeeAllocationPercentage,
_feePercentageDenominator
);
}
function removeLastReferralLevel() external onlyOwner {
require(totalReferralLevels > 0, "Only one referral rank remains. Cannot remove anymore.");
totalReferralLevels = totalReferralLevels.sub(1);
referrerLevels[totalReferralLevels] = ReferrerLevel(
0,
0,
0
);
}
function emergencyRecoverTokens() external onlyOwner {
IERC20(tokenAddress).transfer(
owner(),
IERC20(tokenAddress).balanceOf(address(this))
);
}
function emergencyRecoverEth() external onlyOwner {
uint256 amountToRecover = uint256(address(this).balance).sub(
totalPendingEthRewards
);
require(amountToRecover > 0, "No ETH in contract to recover");
(bool sent, ) = address(owner()).call{value: amountToRecover}("");
require(sent, "Claim failed.");
}
receive() external payable {}
}