Address
0x4e0d5e6e92860f7b3cebc727e1d04d875d061c4eCurrent Holdings
$0.00
TXs sent
not counted
First Active
2025-10-19
block 24,797,465
Last Active
333 days ago
block 24,797,465
Funded By
not identified
Net worth historyi
No net-worth snapshots recorded yet
exact matchAlphaMultiSystem_MAX_LP_Distro_v2solc 0.8.28+commit.7893614aruntime exact · creation exact
// SPDX-License-Identifier: Unlicensed
// ██████ ██████ ████████ ███████ ██████ ██ ██
// ██ ██ ██ ██ ██ ██ ██ ██
// ██ ██ ███ ██ █████ ██ ███████
// ██ ██ ██ ██ ██ ██ ██ ██
// ██████ ██████ ██ ███████ ██████ ██ ██
pragma solidity 0.8.28;
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
}
interface IERC20 {
function totalSupply() external view returns (uint256);
function decimals() external view returns (uint8);
function symbol() external view returns (string memory);
function name() external view returns (string memory);
function getOwner() external view returns (address);
function balanceOf(address account) external view returns (uint256);
function transfer(
address recipient,
uint256 amount
) external returns (bool);
function allowance(
address _owner,
address spender
) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
}
abstract contract Auth {
address internal owner;
mapping(address => bool) internal authorizations;
address[] internal authorizedList;
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
event AddressAuthorized(address indexed account);
event AddressRevoked(address indexed account);
constructor(address _owner, address _authorizedAccount) {
owner = _owner;
authorizations[_owner] = true;
authorizedList.push(_owner);
emit AddressAuthorized(_owner);
if (_authorizedAccount != address(0)) {
authorizations[_authorizedAccount] = true;
authorizedList.push(_authorizedAccount);
emit AddressAuthorized(_authorizedAccount);
}
}
// Modifier to require caller to be owner
modifier onlyOwner() {
require(isOwner(msg.sender), "You Aren't My Daddy");
_;
}
// Modifier to require caller to be authorized
modifier authorized() {
require(isAuthorized(msg.sender), "You Make Me Laugh");
_;
}
// Function to authorize an address
function authorize(address account) public onlyOwner {
require(account != address(0), "You Cant Do That , Ser");
require(!authorizations[account], "Pay Attention Dummy");
authorizations[account] = true;
authorizedList.push(account);
emit AddressAuthorized(account);
}
// Function to revoke authorization
function warningRevokeAuthorization(address account) public onlyOwner {
require(account != address(0), "What Planet Are You From");
require(authorizations[account], "They Were Never Here");
require(account != owner, "Oh, You Got Some Balls");
// Set the authorization status to false
authorizations[account] = false;
// Remove from the authorized list (if you're tracking this in an array)
for (uint256 i = 0; i < authorizedList.length; i++) {
if (authorizedList[i] == account) {
authorizedList[i] = authorizedList[authorizedList.length - 1]; // Replace with last element
authorizedList.pop(); // Remove last element (now a duplicate)
break;
}
}
// Emit event to confirm it was revoked
emit AddressRevoked(account);
}
// Transfer ownership to a new address
function warningTransferOwnership(
address payable newOwner
) public onlyOwner {
emit OwnershipTransferred(owner, newOwner);
authorizations[owner] = false;
owner = newOwner;
authorizations[newOwner] = true;
authorizedList.push(newOwner);
}
// Check if an address is the contract owner
function isOwner(address account) public view returns (bool) {
return account == owner;
}
// Check if an address is authorized
function isAuthorized(address account) public view returns (bool) {
return authorizations[account];
}
// Get total number of authorized addresses
function getAuthorizedCount() public view returns (uint256) {
return authorizedList.length;
}
// See every address in the Authorized List via an index number
function getAuthorizedAddressByIndex(
uint256 index
) public view returns (address) {
require(index < authorizedList.length, "Index out of bounds");
return authorizedList[index];
}
}
interface IDEXFactory {
function createPair(
address tokenA,
address tokenB
) external returns (address pair);
function getPair(
address tokenA,
address tokenB
) external view returns (address pair);
}
interface IDEXPair {
function token0() external view returns (address);
function token1() external view returns (address);
function getReserves()
external
view
returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
}
interface IDEXRouter {
function factory() external pure returns (address);
function WPLS() 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 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;
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);
}
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
}
// Storing this here if another contract ever needs to talk to me
// remove comment out function and insert into other contract
interface IOldDistributor {
// External functions to interact with the contract
function setDistributionCriteria(
uint256 _minPeriod,
uint256 _minDistribution
) external;
function setShare(address shareholder, uint256 amount) external;
function deposit() external payable;
function process(uint256 gas) external;
function claimDividend() external;
function importShares(address externalContract) external;
function importBatchShares(
address externalContract,
uint256 start,
uint256 end
) external;
function exportprimaryTokens()
external
view
returns (address[] memory, address[] memory);
function getShareholderCount() external view returns (uint256);
function getPaidDividends(
address shareholder
) external view returns (uint256);
function getTotalPaid() external view returns (uint256);
function getAllShares() external view returns (Share[] memory);
function getSharesBatches(
uint256 start,
uint256 end
) external view returns (Share[] memory);
function getUnpaidEarnings(
address shareholder
) external view returns (uint256);
// Struct for Shareholder data
struct Share {
address shareholder;
uint256 amount;
uint256 totalExcluded;
uint256 totalRealised;
}
function inAddLiquidity() external view returns (bool);
function getPrimaryTokenCount() external view returns (uint256);
function getPrimaryTokenDetails(
uint256 index
)
external
view
returns (
string memory tokenName,
address tokenAddress,
uint256 sellPercentForMint,
uint256 sellPercentForWPLS,
address wplsReceiver,
uint256 holdAmount
);
function getSecondaryTokenCount() external view returns (uint256);
function getSecondaryTokenDetails(
uint256 index
)
external
view
returns (
string memory tokenName,
address tokenAddress,
bool sellEnabled,
uint256 sellPercent,
address transferReceiver,
uint256 holdAmount
);
}
interface IWPLS {
function deposit() external payable;
function withdraw(uint256) external;
function transfer(address to, uint256 value) external returns (bool);
function balanceOf(address account) external view returns (uint256);
}
interface MintToken is IERC20 {
function externalMint(address to, uint256 amount) external;
}
contract AlphaMultiSystem_MAX_LP_Distro_v2 is ReentrancyGuard, Auth {
using SafeMath for uint256;
struct Share {
address shareholder;
uint256 amount;
uint256 totalExcluded;
uint256 totalRealised;
}
struct PrimaryToken {
string tokenName;
IERC20 token;
uint256 sellPercentForMint;
uint256 sellPercentForWPLS;
address wplsReceiver;
uint256 holdAmount; // ability to bankroll tokens
}
struct SecondaryToken {
string tokenName;
IERC20 token;
bool sellEnabled; // whether we sell some of this token
uint256 sellPercent; // in basis points, % of balance to sell if sellEnabled
address transferReceiver; // address to send excess if not selling
uint256 holdAmount; // minimum balance to keep in contract
}
MintToken public mintToken;
IWPLS constant WPLS = IWPLS(0xA1077a294dDE1B09bB078844df40758a5D0f9a27);
address DEAD = 0x000000000000000000000000000000000000dEaD;
address ZERO = 0x0000000000000000000000000000000000000000;
address BURN = 0x0000000000000000000000000000000000000369;
address v1Router = 0x98bf93ebf5c380C0e6Ae8e192A7e2AE08edAcc02;
address v2Router = 0x165C3410fC91EF562C50559f7d2289fEbed552d9;
address public autoLiquidityReceiver;
PrimaryToken[] primaryTokens;
mapping(address => bool) tokenExists;
SecondaryToken[] secondaryTokens;
mapping(address => bool) secondaryTokenExists;
IDEXRouter public router;
bool initialized;
modifier initialization() {
require(!initialized);
_;
initialized = true;
}
modifier tokenNotExists(address tokenAddress) {
require(!tokenExists[tokenAddress], "Token already exists");
_;
}
bool lpGeneratorEnabled = false;
bool lpGeneratorBackupEnabled = false;
bool public inAddLiquidity;
event SecondaryTokenRemoved(address tokenAddress);
constructor() Auth(msg.sender, address(this)) {
router = IDEXRouter(0x165C3410fC91EF562C50559f7d2289fEbed552d9);
mintToken = MintToken(0x0000000000000000000000000000000000000000);
autoLiquidityReceiver = msg.sender;
}
receive() external payable {
if (msg.value > 0) {
WPLS.deposit{value: msg.value}(); // wrap into WPLS
}
}
function setAutoLpReceiver(address _new) external authorized {
autoLiquidityReceiver = _new;
}
function setMintToken(address _new) external authorized {
mintToken = MintToken(_new);
// Approve the router for max amount
mintToken.approve(address(router), type(uint256).max);
}
function getTokenHoldingsInfo(
address tokenAddress
) external view returns (string memory tokenName, uint256 balance) {
if (tokenAddress == address(0)) {
// ETH balance (address(0) is a common convention for ETH)
tokenName = "WPLS";
balance = address(this).balance;
} else {
// ERC-20 token balance
IERC20 token = IERC20(tokenAddress);
tokenName = token.name();
balance = token.balanceOf(address(this));
}
return (tokenName, balance);
}
// External function to add a PrimaryToken
function addPrimaryToken(address tokenAddress) external authorized {
addPrimary(tokenAddress);
}
function addPrimary(address tokenAddress) private {
require(tokenAddress != address(0), "Invalid token address");
require(!tokenExists[tokenAddress], "Token already added");
if (tokenAddress == address(WPLS)) {
// Special handling for WPLS
primaryTokens.push(
PrimaryToken({
tokenName: "Wrapped PLS",
token: IERC20(address(WPLS)),
sellPercentForMint: 0, // default percentage for mint
sellPercentForWPLS: 0, // default percentage to sell for WPLS
wplsReceiver: address(this), // default to contract itself
holdAmount: 0 // NEW: default hold amount is 0
})
);
tokenExists[address(WPLS)] = true;
IERC20(address(WPLS)).approve(address(router), type(uint256).max);
} else {
// Generic ERC20 path
string memory tokenName = IERC20(tokenAddress).name();
primaryTokens.push(
PrimaryToken({
tokenName: tokenName,
token: IERC20(tokenAddress),
sellPercentForMint: 0, // default percentage for mint
sellPercentForWPLS: 0, // default percentage to sell for WPLS
wplsReceiver: address(this), // default to contract itself
holdAmount: 0 // NEW: default hold amount is 0
})
);
tokenExists[tokenAddress] = true;
IERC20(tokenAddress).approve(address(router), type(uint256).max);
}
}
function updatePrimaryTokenSellPercent(
uint256 index,
uint256 newPercent
) external authorized {
require(index < primaryTokens.length, "Invalid index");
require(newPercent <= 10000, "Max is 10000 (100%)");
primaryTokens[index].sellPercentForMint = newPercent;
}
function updatePrimaryTokenWPLSReceiver(
uint256 index,
address newReceiver
) external authorized {
require(index < primaryTokens.length, "Invalid index");
require(newReceiver != address(0), "Invalid receiver address");
primaryTokens[index].wplsReceiver = newReceiver;
}
function updatePrimaryTokenWPLSPercentage(
uint256 index,
uint256 percent
) external authorized {
require(index < primaryTokens.length, "Invalid index");
require(percent <= 10000, "Percent must be 0-10000");
primaryTokens[index].sellPercentForWPLS = percent;
}
function updatePrimaryTokenHoldAmount(
uint256 index,
uint256 holdAmount
) external authorized {
require(index < primaryTokens.length, "Invalid index");
primaryTokens[index].holdAmount = holdAmount * 10 ** 18;
}
function getPrimaryTokenCount() external view returns (uint256) {
return primaryTokens.length;
}
function _removePrimaryToken(uint256 index) private {
require(index < primaryTokens.length, "Invalid index");
address tokenAddress = address(primaryTokens[index].token);
// Transfer remaining balance to the caller
uint256 remainingBalance = primaryTokens[index].token.balanceOf(
address(this)
);
if (remainingBalance > 0) {
primaryTokens[index].token.transfer(msg.sender, remainingBalance);
}
// Remove the token from the array efficiently
primaryTokens[index] = primaryTokens[primaryTokens.length - 1];
primaryTokens.pop();
// Clean up the mapping
tokenExists[tokenAddress] = false;
emit TokenRemoved(tokenAddress);
}
function removePrimaryToken(uint256 index) external authorized {
_removePrimaryToken(index);
}
function removeAllPrimaryTokens() external authorized {
for (uint256 i = primaryTokens.length; i > 0; i--) {
_removePrimaryToken(i - 1);
}
}
event TokenRemoved(address tokenAddress);
function getPrimaryTokenDetails(
uint256 index
)
external
view
returns (
string memory tokenName,
address tokenAddress,
uint256 sellPercentForMint,
uint256 sellPercentForWPLS,
address wplsReceiver,
uint256 holdAmount
)
{
require(index < primaryTokens.length, "Invalid index");
PrimaryToken storage primaryToken = primaryTokens[index];
return (
primaryToken.tokenName,
address(primaryToken.token),
primaryToken.sellPercentForMint,
primaryToken.sellPercentForWPLS,
primaryToken.wplsReceiver,
primaryToken.holdAmount
);
}
function addSecondaryToken(address tokenAddress) external authorized {
addSecondary(tokenAddress);
}
function addSecondary(address tokenAddress) private {
require(tokenAddress != address(0), "Invalid token address");
require(!secondaryTokenExists[tokenAddress], "Token already added");
string memory tokenName = IERC20(tokenAddress).name();
IERC20(tokenAddress).approve(address(router), type(uint256).max);
secondaryTokens.push(
SecondaryToken({
tokenName: tokenName,
token: IERC20(tokenAddress),
sellEnabled: false, // default: don't sell
sellPercent: 10000, // default: 100% if sell enabled
transferReceiver: tokenAddress, // default: self
holdAmount: type(uint256).max // default: max balance
})
);
secondaryTokenExists[tokenAddress] = true;
}
function _removeSecondaryToken(uint256 index) private {
require(index < secondaryTokens.length, "Invalid index");
address tokenAddress = address(secondaryTokens[index].token);
// Transfer remaining balance of the token back to caller (if any)
uint256 remainingBalance = secondaryTokens[index].token.balanceOf(
address(this)
);
if (remainingBalance > 0) {
secondaryTokens[index].token.transfer(msg.sender, remainingBalance);
}
// Swap-and-pop to keep array packed
if (index != secondaryTokens.length - 1) {
secondaryTokens[index] = secondaryTokens[
secondaryTokens.length - 1
];
}
secondaryTokens.pop();
// Clean up mapping
secondaryTokenExists[tokenAddress] = false;
emit SecondaryTokenRemoved(tokenAddress);
}
function removeSecondaryToken(uint256 index) external authorized {
_removeSecondaryToken(index);
}
function removeAllSecondaryTokens() external authorized {
for (uint256 i = secondaryTokens.length; i > 0; i--) {
_removeSecondaryToken(i - 1);
}
}
function getSecondaryTokenDetails(
uint256 index
)
external
view
returns (
string memory tokenName,
address tokenAddress,
bool sellEnabled,
uint256 sellPercent,
address transferReceiver,
uint256 holdAmount
)
{
require(index < secondaryTokens.length, "Invalid index");
SecondaryToken storage sToken = secondaryTokens[index];
return (
sToken.tokenName,
address(sToken.token),
sToken.sellEnabled,
sToken.sellPercent,
sToken.transferReceiver,
sToken.holdAmount
);
}
function getSecondaryTokenCount() external view returns (uint256) {
return secondaryTokens.length;
}
function setSecondarySellConfig(
uint256 index,
bool enabled,
uint256 percent
) external authorized {
require(index < secondaryTokens.length, "Invalid index");
require(percent <= 10000, "Max 10000 (100%)");
SecondaryToken storage sec = secondaryTokens[index];
sec.sellEnabled = enabled;
sec.sellPercent = percent;
}
function setSecondaryTransferReceiver(
uint256 index,
address receiver
) external authorized {
require(index < secondaryTokens.length, "Invalid index");
require(receiver != address(0), "Invalid address");
secondaryTokens[index].transferReceiver = receiver;
}
function setSecondaryHoldAmount(
uint256 index,
uint256 amount
) external authorized {
require(index < secondaryTokens.length, "Invalid index");
secondaryTokens[index].holdAmount = amount * 10 ** 18;
}
// ---------------------------------------------------------------------
// Import Data from Old LP Distro
// ---------------------------------------------------------------------
function importPrimaryFromOld(address oldContract) external authorized {
IOldDistributor old = IOldDistributor(oldContract);
uint256 count = old.getPrimaryTokenCount();
for (uint256 i = 0; i < count; i++) {
(
, // skip tokenName
address tokenAddr,
uint256 sellMint,
uint256 sellWPLS,
address wplsRecv,
uint256 holdAmount
) = old.getPrimaryTokenDetails(i);
// Add token to new contract
addPrimary(tokenAddr);
// Set percentages, receiver, and hold amount
uint256 index = primaryTokens.length - 1;
primaryTokens[index].sellPercentForMint = sellMint;
primaryTokens[index].sellPercentForWPLS = sellWPLS;
primaryTokens[index].wplsReceiver = wplsRecv == address(0)
? address(this)
: wplsRecv;
primaryTokens[index].holdAmount = holdAmount;
}
}
function importSecondaryFromOld(address oldContract) external authorized {
IOldDistributor old = IOldDistributor(oldContract);
uint256 count = old.getSecondaryTokenCount();
for (uint256 i = 0; i < count; i++) {
(
, // skip tokenName
address tokenAddr,
bool sellEnabled,
uint256 sellPercent,
address receiver,
uint256 holdAmount
) = old.getSecondaryTokenDetails(i);
// Add token to new contract
addSecondary(tokenAddr);
// Set config
uint256 index = secondaryTokens.length - 1;
secondaryTokens[index].sellEnabled = sellEnabled;
secondaryTokens[index].sellPercent = sellPercent;
secondaryTokens[index].transferReceiver = receiver == address(0)
? address(this)
: receiver;
secondaryTokens[index].holdAmount = holdAmount;
}
}
// ---------------------------------------------------------------------
// Import Data from Old LP Distro End
// ---------------------------------------------------------------------
function recoverLostTokens(
address _lostToken,
address _destination
) external authorized nonReentrant {
if (_lostToken == address(0)) {
uint256 ethAmount = address(this).balance;
require(ethAmount > 0, "No Cookies in the Jar");
payable(_destination).transfer(ethAmount);
} else {
uint256 tokenAmount = IERC20(_lostToken).balanceOf(address(this));
require(tokenAmount > 0, "No Tokens Left All Gone");
IERC20(_lostToken).transfer(_destination, tokenAmount);
}
}
function recoverLostTokensPercentage(
address tokenAddy,
uint256 percentage
) external authorized nonReentrant {
require(percentage > 0 && percentage <= 100, "Invalid percentage");
if (tokenAddy == address(0)) {
// Handle raw gas token (native coin like ETH or WPLS)
uint256 gasAmount = address(this).balance;
require(gasAmount > 0, "I'm Broke, Go Away");
uint256 amountToSend = (gasAmount * percentage) / 100;
payable(msg.sender).transfer(amountToSend);
} else {
// Handle ERC20 tokens
uint256 tokenAmount = IERC20(tokenAddy).balanceOf(address(this));
require(tokenAmount > 0, "No Tokens To Recover");
uint256 amountToSend = (tokenAmount * percentage) / 100;
IERC20(tokenAddy).transfer(msg.sender, amountToSend);
}
}
function recoverAllTokens(
address _destination
) external authorized nonReentrant {
uint256 ethAmount = address(this).balance;
uint256 totalRecovered = ethAmount;
// ✅ Recover native PLS
if (ethAmount > 0) {
payable(_destination).transfer(ethAmount);
}
// ✅ Recover all ERC20 PrimaryTokens
for (uint256 i = 0; i < primaryTokens.length; i++) {
PrimaryToken storage primary = primaryTokens[i];
uint256 tokenAmount = IERC20(address(primary.token)).balanceOf(
address(this)
);
if (tokenAmount > 0) {
IERC20(address(primary.token)).transfer(
_destination,
tokenAmount
);
totalRecovered += tokenAmount;
}
}
// ✅ Recover all ERC20 secondary tokens
for (uint256 i = 0; i < secondaryTokens.length; i++) {
SecondaryToken storage sec = secondaryTokens[i];
uint256 tokenAmount = IERC20(address(sec.token)).balanceOf(
address(this)
);
if (tokenAmount > 0) {
IERC20(address(sec.token)).transfer(_destination, tokenAmount);
totalRecovered += tokenAmount;
}
}
// ✅ Recover mintToken balance
uint256 mintTokenAmount = IERC20(address(mintToken)).balanceOf(
address(this)
);
if (mintTokenAmount > 0) {
IERC20(address(mintToken)).transfer(_destination, mintTokenAmount);
totalRecovered += mintTokenAmount;
}
// ✅ Ensure something was recovered
require(
totalRecovered > 0,
"Ok, Debo you already check my pockets... Chill !!!"
);
}
function deposit() external payable authorized nonReentrant {
require(msg.value > 0, "Must send PLS to deposit");
if (inAddLiquidity) return; // recursion guard
inAddLiquidity = true;
// Wrap PLS
WPLS.deposit{value: msg.value}();
// LP generators
if (generatorPrimed()) tokenLPGenerator();
if (tokenBackUpGeneratorPrimed()) tokenLPGeneratorBackup();
// Process secondary tokens
processSecondaryTokens();
inAddLiquidity = false;
}
function processSecondaryTokens() private {
for (uint256 i = 0; i < secondaryTokens.length; i++) {
SecondaryToken storage sec = secondaryTokens[i];
uint256 balance = IERC20(address(sec.token)).balanceOf(
address(this)
);
// Skip if nothing to process
if (balance == 0) continue;
// Calculate amount above holdAmount
uint256 excess = balance > sec.holdAmount
? balance - sec.holdAmount
: 0;
if (excess == 0) continue;
if (sec.sellEnabled && sec.sellPercent > 0) {
// Sell the configured percentage of excess for mintToken
uint256 sellAmount = (excess * sec.sellPercent) / 10000;
if (sellAmount > 0) {
address[] memory path = new address[](2);
path[0] = address(sec.token);
path[1] = address(WPLS);
IERC20(address(sec.token)).approve(
address(router),
sellAmount
);
try
router
.swapExactTokensForTokensSupportingFeeOnTransferTokens(
sellAmount,
0,
path,
address(this),
block.timestamp
)
{} catch {}
}
}
// Transfer remaining excess to receiver if set
uint256 remaining = IERC20(address(sec.token)).balanceOf(
address(this)
) - sec.holdAmount;
if (remaining > 0 && sec.transferReceiver != address(0)) {
IERC20(address(sec.token)).transfer(
sec.transferReceiver,
remaining
);
}
}
}
function tokenLPGeneratorBackup() private {
if (primaryTokens.length == 0) return;
for (uint256 i = 0; i < primaryTokens.length; i++) {
PrimaryToken storage primaryToken = primaryTokens[i];
address token = address(primaryToken.token);
if (token == address(0)) continue;
address pair = IDEXFactory(IDEXRouter(router).factory()).getPair(
token,
address(this)
);
if (pair == address(0)) continue;
(uint112 reserve0, uint112 reserve1, ) = IDEXPair(pair)
.getReserves();
(uint112 reserveToken, uint112 reserveProject) = token <
address(this)
? (reserve0, reserve1)
: (reserve1, reserve0);
// 🔸 Handle sell portion (holdAmount respected inside)
if (
primaryToken.sellPercentForMint > 0 ||
primaryToken.sellPercentForWPLS > 0
) {
_processPrimaryTokenSells(primaryToken, token);
}
// 🔹 Respect hold amount after selling
uint256 tokenBalance = IERC20(token).balanceOf(address(this));
uint256 availableToken;
// If holdAmount is set and there’s excess, use only the excess
if (primaryToken.holdAmount > 0) {
if (tokenBalance <= primaryToken.holdAmount) {
continue; // Not enough to use, skip this token entirely
}
availableToken = tokenBalance - primaryToken.holdAmount;
} else {
availableToken = tokenBalance; // No holdAmount, use full balance
}
// 🔹 Skip minting if availableToken is 0
if (availableToken == 0) {
continue;
}
// 🟢 STEP 2: Calculate how much project tokens to mint based on current pool ratio
uint256 amountProject = reserveToken > 0
? (availableToken * reserveProject) / reserveToken
: availableToken;
// Mint project tokens to contract
mintToken.externalMint(address(this), amountProject);
if (amountProject == 0) continue;
// Approve for router
IERC20(address(mintToken)).approve(address(router), amountProject);
IERC20(token).approve(address(router), availableToken);
try
router.addLiquidity(
token,
address(mintToken),
availableToken,
amountProject,
(availableToken * 75) / 100,
(amountProject * 75) / 100,
autoLiquidityReceiver,
block.timestamp
)
{} catch {
continue;
}
}
}
function tokenLPGenerator() private {
if (primaryTokens.length == 0) return;
for (uint256 i = 0; i < primaryTokens.length; i++) {
PrimaryToken storage primaryToken = primaryTokens[i];
address token = address(primaryToken.token);
if (token == address(0)) continue;
address pair = IDEXFactory(IDEXRouter(router).factory()).getPair(
token,
address(mintToken)
);
if (pair == address(0)) continue;
(uint112 reserve0, uint112 reserve1, ) = IDEXPair(pair)
.getReserves();
(uint112 reserveToken, uint112 reserveProject) = token <
address(mintToken)
? (reserve0, reserve1)
: (reserve1, reserve0);
// 🔸 Handle sell portion (holdAmount respected inside)
if (
primaryToken.sellPercentForMint > 0 ||
primaryToken.sellPercentForWPLS > 0
) {
_processPrimaryTokenSells(primaryToken, token);
}
// 🔹 Respect hold amount after selling
uint256 tokenBalance = IERC20(token).balanceOf(address(this));
uint256 availableToken;
if (primaryToken.holdAmount > 0) {
if (tokenBalance <= primaryToken.holdAmount) {
continue; // Not enough to use, skip this token
}
availableToken = tokenBalance - primaryToken.holdAmount;
} else {
availableToken = tokenBalance; // No holdAmount, use full balance
}
// 🔹 Skip if nothing to use
if (availableToken == 0) continue;
// 🟢 STEP 2: Calculate how much project tokens to use based on current pool ratio
uint256 projectTokenBalance = IERC20(mintToken).balanceOf(
address(this)
);
if (projectTokenBalance == 0) continue;
uint256 amountProject = reserveToken > 0
? (availableToken * reserveProject) / reserveToken
: availableToken;
if (amountProject == 0) continue;
// Cap project token usage to contract balance
if (amountProject > projectTokenBalance) {
amountProject = projectTokenBalance;
amountProject = reserveProject > 0
? (amountProject * reserveToken) / reserveProject
: amountProject;
}
// Approve for router
IERC20(address(mintToken)).approve(address(router), amountProject);
IERC20(token).approve(address(router), availableToken);
// Add liquidity using only availableToken and corresponding project tokens
try
router.addLiquidity(
token,
address(mintToken),
availableToken,
amountProject,
(availableToken * 75) / 100,
(amountProject * 75) / 100,
autoLiquidityReceiver,
block.timestamp
)
{} catch {
continue;
}
}
}
function _processPrimaryTokenSells(
PrimaryToken storage primaryToken,
address token
) private {
uint256 tokenBalance = IERC20(token).balanceOf(address(this));
if (tokenBalance == 0) return;
// 🔹 Respect hold amount
if (
primaryToken.holdAmount > 0 &&
tokenBalance <= primaryToken.holdAmount
) {
return; // nothing to sell
}
uint256 availableToken = tokenBalance;
if (primaryToken.holdAmount > 0) {
availableToken = tokenBalance - primaryToken.holdAmount;
}
uint256 sellAmountForMint;
uint256 sellAmountForWPLS;
if (primaryToken.sellPercentForMint > 0) {
uint256 totalSellAmount = (availableToken *
primaryToken.sellPercentForMint) / 10000;
sellAmountForWPLS =
(totalSellAmount * primaryToken.sellPercentForWPLS) / 10000;
sellAmountForMint = totalSellAmount - sellAmountForWPLS;
} else {
sellAmountForMint = 0;
sellAmountForWPLS =
(availableToken * primaryToken.sellPercentForWPLS) / 10000;
}
// 🔹 Sell for MintToken
if (sellAmountForMint > 0) {
IERC20(token).approve(address(router), sellAmountForMint);
address[] memory path = new address[](2);
path[0] = token;
path[1] = address(mintToken);
try
router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
sellAmountForMint,
0,
path,
address(this),
block.timestamp
)
{} catch {}
}
// 🔹 Sell for WPLS
if (sellAmountForWPLS > 0) {
IERC20(token).approve(address(router), sellAmountForWPLS);
address[] memory pathWPLS = new address[](2);
pathWPLS[0] = token;
pathWPLS[1] = address(WPLS);
try
router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
sellAmountForWPLS,
0,
pathWPLS,
address(this),
block.timestamp
)
{} catch {}
// Send WPLS to receiver if set
uint256 wplsBalance = WPLS.balanceOf(address(this));
if (wplsBalance > 0) {
address receiver = primaryToken.wplsReceiver == address(0)
? address(this)
: primaryToken.wplsReceiver;
WPLS.transfer(receiver, wplsBalance);
}
}
}
function generatorPrimed() internal view returns (bool) {
return lpGeneratorEnabled;
}
function tokenBackUpGeneratorPrimed() internal view returns (bool) {
return lpGeneratorBackupEnabled;
}
function warningMainGeneratorOveride() external authorized {
lpGeneratorEnabled = true;
lpGeneratorBackupEnabled = false;
}
function warningBackupGeneratorOveride() external authorized {
lpGeneratorEnabled = false;
lpGeneratorBackupEnabled = true;
}
function warningManualGeneratorOveride(
bool _lpStatus,
bool _lpBackUpStatus
) external authorized {
lpGeneratorEnabled = _lpStatus;
lpGeneratorBackupEnabled = _lpBackUpStatus;
}
function getContractStatus()
external
view
returns (bool LP_Generator_On, bool LP_Generator_Backup_on)
{
return (lpGeneratorEnabled, lpGeneratorBackupEnabled);
}
}