Address
0x35f531e5f5cd254dfe79bc500aee025ea63fe55dCurrent Holdings
$0.00
TXs sent
not counted
First Active
2025-03-05
block 22,871,278
Last Active
354 days ago
block 24,606,987
Funded By
not identified
Net worth historyi
95 snapshots · to block 27,488,945coverage change 26 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Aug
partial matchKSBTsolc 0.8.30+commit.73712a01runtime partial · creation not verified
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
interface IPulseXRouter {
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 swapExactTokensForTokensSupportingFeeOnTransferTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external;
function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] calldata amounts);
}
interface IPulseXFactory {
function createPair(address tokenA, address tokenB) external returns (address pair);
function getPair(address tokenA, address tokenB) external view returns (address pair);
}
error FailedToTransfer(address from, address to, uint256 amount);
error InsufficientAllowance(uint256 amount);
error InsufficientBalance(uint256 amount);
error InvalidAddress(address _address);
error LPDoesNotExist(address tokenA, address tokenB);
error LPMinimumTooLow(uint256 amount);
error OverMaxTransferAmount(uint256 amount);
error TaxIsTooHigh(uint256 percent);
contract KSBT is Ownable (msg.sender) {
using SafeERC20 for IERC20;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
string public name = "DOUBT";
string public symbol = unicode"DOUBT";
uint256 public decimals = 18;
uint256 public totalSupply = 5555 * 10**decimals;
bool public taxActivated;
uint64 public taxPercent;
address public taxReceiverAddress;
mapping(address => bool) public taxExempt;
mapping(address => bool) public taxTrigger;
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
IERC20 SelfERC20 = IERC20(address(this));
IERC20 KSBERC20;
IERC20 WPLSERC20 = IERC20(address(0xA1077a294dDE1B09bB078844df40758a5D0f9a27));
IPulseXRouter PulseXV1Router = IPulseXRouter(address(0x98bf93ebf5c380C0e6Ae8e192A7e2AE08edAcc02));
IPulseXRouter PulseXV2Router = IPulseXRouter(address(0x165C3410fC91EF562C50559f7d2289fEbed552d9));
IPulseXFactory PulseXV1Factory = IPulseXFactory(address(0x1715a3E4A142d8b698131108995174F37aEBA10D));
IPulseXFactory PulseXV2Factory = IPulseXFactory(address(0x29eA7545DEf87022BAdc76323F373EA1e707C523));
bool reLockOn = false;
bool lpActivated = true;
address public lpTokenA;
address public lpTokenB;
uint256 lpMinAmount = 0;
constructor(uint64 _taxPercent, address _tokenAddress, bool _taxActivated, bool _lpActivated) {
require(_tokenAddress != address(0), "Set the address for the main token");
KSBERC20 = IERC20(_tokenAddress);
// set initial tax configs
taxReceiverAddress = msg.sender;
taxPercent = _taxPercent; // 1% is 100, 100% is 10000
taxActivated = _taxActivated;
// set initial lpc onfigs
lpActivated = _lpActivated;
lpTokenA = _tokenAddress;
lpTokenB = address(this);
// set deployer as tax exempt
taxExempt[msg.sender] = true;
// create empty pairs
address lpAddressV1 = PulseXV1Factory.createPair(_tokenAddress, address(this));
address lpAddressV2 = PulseXV2Factory.createPair(_tokenAddress, address(this));
address lpSelfWPLSV1 = PulseXV1Factory.createPair(address(this), address(WPLSERC20));
address lpSelfWPLSV2 = PulseXV2Factory.createPair(address(this), address(WPLSERC20));
// set them as taxable triggers
taxTrigger[lpAddressV1] = true;
taxTrigger[lpAddressV2] = true;
taxTrigger[lpSelfWPLSV1] = true;
taxTrigger[lpSelfWPLSV2] = true;
// approve pulsex v1 and v2 to spend tokens belonging to this contract
allowance[address(this)][address(PulseXV1Router)] = type(uint256).max;
allowance[address(this)][address(PulseXV2Router)] = type(uint256).max;
// send initial supply to the deployer
balanceOf[msg.sender] = totalSupply;
emit Transfer(address(0), msg.sender, totalSupply);
}
receive() external payable { }
modifier reLock() {
// reentrant lock
reLockOn = true;
_;
reLockOn = false;
}
function approve(address spender, uint256 amount) public {
// approve spender to access tokens using transferFrom
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
}
function _transferWithFees(address from, address to, uint256 amount, uint256 fees) internal {
// add amount to receiver
(bool taxSuccess, uint256 amountSubFee) = Math.trySub(amount, fees);
(bool toSuccess, uint256 toBalance) = Math.tryAdd(balanceOf[to], amountSubFee);
if (taxSuccess)
if (toSuccess)
balanceOf[to] = toBalance;
// sub amount from sender
(bool fromSuccess, uint256 fromBalance) = Math.trySub(balanceOf[from], amount);
if (fromSuccess)
balanceOf[from] = fromBalance;
// check if both actions succeeded and emit or revert
if (fromSuccess && toSuccess && taxSuccess)
emit Transfer(from, to, amountSubFee);
else
revert FailedToTransfer(from, to, amount);
}
function _transfer(address from, address to, uint256 amount) internal {
// transfer like normal if reLock engaged
uint256 fees = 0;
if (!reLockOn) {
// check balance
if (balanceOf[from] < amount)
revert InsufficientBalance(amount);
// get amount to send with/without tax
if (triggerTax(from, to)) {
if (triggerSwapForLP())
swapForLP();
if (!isTaxExempt(from, to))
if (taxActivated)
fees = takeTax(from, amount);
}
}
// transfer the final amount
_transferWithFees(from, to, amount, fees);
}
function transfer(address to, uint256 amount) public {
// transfer token amount from source
_transfer(msg.sender, to, amount);
}
function transferFrom(address from, address to, uint256 amount) public {
// check allowance
if (allowance[from][msg.sender] < amount)
revert InsufficientAllowance(amount);
// transfer token amount
_transfer(from, to, amount);
}
function triggerTax(address from, address to) internal view returns (bool) {
// triggers on known lp pools or other addresses
if (taxTrigger[from] || taxTrigger[to])
return true;
return false;
}
function approveToken(IERC20 token, IPulseXRouter router) internal returns (bool) {
// approves any erc20 with a chosen router for this contract
if (token.allowance(address(this), address(router)) < (type(uint256).max / 2))
token.approve(address(router), type(uint256).max);
return true;
}
function triggerSwapForLP() internal view returns (bool) {
// triggers if enough tokens accrued with lp activated and reentrant is not locked
if (!reLockOn
&& lpActivated
&& balanceOf[address(this)] >= lpMinAmount)
return true;
return false;
}
function getBetterRouterForPath(uint256 amount, address[] memory lpPath) internal view returns (bool, IPulseXRouter, uint256) {
IPulseXRouter router;
uint256 outputAmount;
// check pulsex v1
uint256 tokenAmountV1 = 0;
try PulseXV1Router.getAmountsOut(
amount,
lpPath
) returns (uint256[] memory amountOutMinV1) {
tokenAmountV1 = amountOutMinV1[amountOutMinV1.length - 1];
} catch {}
// check pulsex v2
uint256 tokenAmountV2 = 0;
try PulseXV2Router.getAmountsOut(
amount,
lpPath
) returns (uint256[] memory amountOutMinV2) {
tokenAmountV2 = amountOutMinV2[amountOutMinV2.length - 1];
} catch {}
// compare the output amounts
if (tokenAmountV1 >= tokenAmountV2) {
router = PulseXV1Router;
outputAmount = tokenAmountV1;
} else {
router = PulseXV2Router;
outputAmount = tokenAmountV2;
}
// sucess if one of the amounts is not zero
// return the better router and output amount
return (tokenAmountV1 != 0 && tokenAmountV2 != 0, router, outputAmount);
}
function getBetterPathAndRouter(uint256 amount, address tokenA, address tokenB) internal view returns (bool, address[] memory, IPulseXRouter) {
// route with two hops
address[] memory lpPath3 = new address[](3);
lpPath3[0] = tokenA == address(this) ? address(this) : tokenA;
lpPath3[1] = address(WPLSERC20);
lpPath3[2] = tokenB == address(this) ? address(this) : tokenB;
// route with one hop
address[] memory lpPath2 = new address[](2);
lpPath2[0] = lpPath3[0];
lpPath2[1] = lpPath3[2];
// find and return the best router
(bool success1, IPulseXRouter router1, uint256 outputAmount1) = getBetterRouterForPath(amount, lpPath3);
(bool success2, IPulseXRouter router2, uint256 outputAmount2) = getBetterRouterForPath(amount, lpPath2);
// both paths resulted in a router
if (success1 && success2)
// check the best result of those
if (outputAmount1 < outputAmount2)
return (true, lpPath2, router2);
// only one of the paths were found
if (success1)
return (true, lpPath3, router1);
// default to the other path
return (true, lpPath2, router2);
}
function swapForLP() public reLock {
if (lpTokenA == address(this))
if (lpTokenB == address(this))
return;
// get the balance of this token in the contract and divide in half
uint256 splitAmount = (balanceOf[address(this)] / 2);
// get the better path and router based on estimates
(bool successA, address[] memory lpPathA, IPulseXRouter routerA) = getBetterPathAndRouter(splitAmount, address(this), lpTokenA);
(bool successB, address[] memory lpPathB, IPulseXRouter routerB) = getBetterPathAndRouter(splitAmount, address(this), lpTokenB);
// perform the swap if routes were found
if (successA)
if (successB) {
// first half
if (lpTokenA != address(this))
routerA.swapExactTokensForTokensSupportingFeeOnTransferTokens(
splitAmount,
0,
lpPathA,
taxReceiverAddress, // receiver
block.timestamp
);
// second half
if (lpTokenB != address(this))
routerB.swapExactTokensForTokensSupportingFeeOnTransferTokens(
splitAmount,
0,
lpPathB,
taxReceiverAddress, // receiver
block.timestamp
);
// send the other half if one of the swaps were skipped
if (lpTokenA == address(this) || lpTokenB == address(this))
_transferWithFees(
address(this),
taxReceiverAddress, // receiver
splitAmount,
0 // ignore fee
);
}
}
function setLPSwapState(bool state) public onlyOwner {
// set lp swap enabled/disabled
lpActivated = state;
}
function setLP(address tokenA, address tokenB) public onlyOwner returns (bool) {
// update lp tokenA/B values
// must be matched with a companion contract receiving the tokens
if (tokenA != address(0))
if (tokenB != address(0)) {
lpTokenA = tokenA;
lpTokenB = tokenB;
return true;
}
return false;
}
function takeTax(address from, uint256 amount) internal returns (uint256) {
// returns the amount after taking fees
uint256 fees = 0;
if (!taxExempt[from]) {
// 1% is represented as 100 so dividing should be 10000
fees = Math.mulDiv(amount, taxPercent, 10000);
// add fees taken to contract balances
balanceOf[address(this)] += fees;
// emit transfer event for the fees taken
emit Transfer(from, address(this), fees);
}
return fees;
}
function setTaxExempt(address _address, bool _exemption) public onlyOwner {
// set tax exempt enabled/disabled per address
taxExempt[_address] = _exemption;
}
function isTaxExempt(address from, address to) view public returns (bool) {
// from sender only to prevent abusing lp
return taxExempt[from] || taxExempt[to];
}
function setTaxPercent(uint64 percent) public onlyOwner {
// set tax fee percent out of 100
if (percent >= 10000)
revert TaxIsTooHigh(percent);
taxPercent = percent;
}
function setTaxState(bool state) public onlyOwner {
// set tax enabled/disabled
taxActivated = state;
}
function setTaxReceiver(address _address) public onlyOwner {
// set receiver of lp tokens
taxReceiverAddress = _address;
}
function setTaxableTrigger(address _address, bool state) public onlyOwner {
// enable/disable tax for addresses to/from
// opposite effect of taxExempt
taxTrigger[_address] = state;
}
function withdrawPLS() public onlyOwner {
// sends any pls in the balance to the contract owner
payable(owner()).transfer(address(this).balance);
}
function withdrawERC20(address token) public onlyOwner {
// sends any erc20 in the balance to the contract owner
IERC20 tokenERC20 = IERC20(token);
tokenERC20.transfer(owner(), tokenERC20.balanceOf(address(this)));
}
}