Address
0x0ab0c9c78a63793e36cb861b8dceee8b4a65e2ceCurrent Holdings
$0.00
TXs sent
0
First Active
2026-05-04
block 26,447,863
Last Active
today
block 27,562,292
Funded By
not identified
Net worth historyi
1,537 snapshots · to block 27,565,373coverage change 26 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Aug
exact matchPMINTFeeRouterV5solc 0.8.19+commit.7dd6d404runtime exact · creation exact
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/v4.9.3/contracts/token/ERC20/IERC20.sol";
import "https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/v4.9.3/contracts/token/ERC20/utils/SafeERC20.sol";
import "https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/v4.9.3/contracts/security/ReentrancyGuard.sol";
interface IUniswapV2Router {
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 getAmountsOut(uint256 amountIn, address[] calldata path)
external view returns (uint256[] memory);
}
interface IUniswapV2Pair {
function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external;
function getReserves() external view returns (uint112 r0, uint112 r1, uint32);
function token0() external view returns (address);
function token1() external view returns (address);
}
contract PMINTFeeRouterV5 is ReentrancyGuard {
using SafeERC20 for IERC20;
uint256 public constant FEE_BPS = 30;
uint256 public constant BPS_BASE = 10_000;
uint256 public constant MIN_BUYBURN = 10 * 1e18; // 10 pDAI min before buyburn
address public constant BURN_ADDR = 0x000000000000000000000000000000000000dEaD;
address public immutable pulseXRouter;
address public immutable pmintToken;
address public immutable pdai;
address public immutable wpls;
address public immutable plsPdaiPair;
uint256 public pendingBuyback;
event SwapExecuted(address indexed user, address tokenIn, address tokenOut, uint256 amountIn, uint256 feeAmount);
event BuyBurnExecuted(uint256 pdaiSpent, uint256 pmintBurned);
// Struct to bypass "Stack Too Deep" errors
struct SwapCache {
address tokenIn;
address tokenOut;
uint256 swapAmount;
uint256 feeAmt;
uint256 pdaiBalBefore;
}
constructor(
address _router,
address _pmintToken,
address _pdai,
address _wpls,
address _plsPdaiPair
) {
require(_router != address(0));
require(_pmintToken != address(0));
require(_pdai != address(0));
require(_wpls != address(0));
require(_plsPdaiPair != address(0));
pulseXRouter = _router;
pmintToken = _pmintToken;
pdai = _pdai;
wpls = _wpls;
plsPdaiPair = _plsPdaiPair;
}
// ─────────────────────────────────────────────────────────────────────────
// TOKEN TO TOKEN
// ─────────────────────────────────────────────────────────────────────────
function swapTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external nonReentrant {
require(path.length >= 2, "Bad path");
SwapCache memory v;
v.tokenIn = path[0];
v.tokenOut = path[path.length - 1];
uint256 balBefore = IERC20(v.tokenIn).balanceOf(address(this));
IERC20(v.tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);
v.swapAmount = IERC20(v.tokenIn).balanceOf(address(this)) - balBefore;
if (v.tokenIn == pdai) {
v.feeAmt = (v.swapAmount * FEE_BPS) / BPS_BASE;
v.swapAmount -= v.feeAmt;
_accumulateFee(v.feeAmt);
}
v.pdaiBalBefore = (v.tokenOut == pdai) ? IERC20(pdai).balanceOf(address(this)) : 0;
_executeRouterSwap(v.swapAmount, amountOutMin, path, to, deadline, v.tokenOut == pdai);
if (v.tokenOut == pdai) {
uint256 pdaiOut = IERC20(pdai).balanceOf(address(this)) - v.pdaiBalBefore;
if (pdaiOut > 0) {
uint256 outDiv = (pdaiOut * FEE_BPS) / BPS_BASE;
v.feeAmt += outDiv;
_accumulateFee(outDiv);
IERC20(pdai).safeTransfer(to, pdaiOut - outDiv);
}
}
emit SwapExecuted(msg.sender, v.tokenIn, v.tokenOut, amountIn, v.feeAmt);
}
// ─────────────────────────────────────────────────────────────────────────
// INTERNAL HELPERS
// ─────────────────────────────────────────────────────────────────────────
function _executeRouterSwap(
uint256 swapAmount,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline,
bool outIsPDAI
) internal {
IERC20(path[0]).approve(pulseXRouter, swapAmount);
IUniswapV2Router(pulseXRouter).swapExactTokensForTokensSupportingFeeOnTransferTokens(
swapAmount,
amountOutMin,
path,
outIsPDAI ? address(this) : to,
deadline
);
IERC20(path[0]).approve(pulseXRouter, 0);
}
function _getReserves(address tokenIn) internal view returns (uint256 rIn, uint256 rOut) {
(uint112 r0, uint112 r1,) = IUniswapV2Pair(plsPdaiPair).getReserves();
address t0 = IUniswapV2Pair(plsPdaiPair).token0();
(rIn, rOut) = t0 == tokenIn ? (uint256(r0), uint256(r1)) : (uint256(r1), uint256(r0));
}
function _getAmountOut(uint256 amtIn, uint256 rIn, uint256 rOut) internal pure returns (uint256) {
uint256 amtInWithFee = amtIn * 9971;
return (amtInWithFee * rOut) / (rIn * 10000 + amtInWithFee);
}
// ─────────────────────────────────────────────────────────────────────────
// PLS TO pDAI
// ─────────────────────────────────────────────────────────────────────────
function swapPLSForPDAI(
uint256 amountOutMin,
address to,
uint256 deadline
) external payable nonReentrant {
require(msg.value > 0, "No PLS");
require(block.timestamp <= deadline, "Expired");
(bool ok,) = wpls.call{value: msg.value}("");
require(ok, "WPLS wrap failed");
(uint256 rIn, uint256 rOut) = _getReserves(wpls);
uint256 pdaiOut = _getAmountOut(msg.value, rIn, rOut);
require(pdaiOut >= amountOutMin, "Slippage");
bool wplsIsT0 = IUniswapV2Pair(plsPdaiPair).token0() == wpls;
IERC20(wpls).safeTransfer(plsPdaiPair, msg.value);
uint256 pdaiBalBefore = IERC20(pdai).balanceOf(address(this));
IUniswapV2Pair(plsPdaiPair).swap(
wplsIsT0 ? 0 : pdaiOut,
wplsIsT0 ? pdaiOut : 0,
address(this), bytes("")
);
uint256 received = IERC20(pdai).balanceOf(address(this)) - pdaiBalBefore;
require(received > 0, "No pDAI received");
uint256 feeAmt = (received * FEE_BPS) / BPS_BASE;
_accumulateFee(feeAmt);
IERC20(pdai).safeTransfer(to, received - feeAmt);
emit SwapExecuted(msg.sender, address(0), pdai, msg.value, feeAmt);
}
// ─────────────────────────────────────────────────────────────────────────
// pDAI TO PLS
// ─────────────────────────────────────────────────────────────────────────
function swapPDAIForPLS(
uint256 amountIn,
uint256 amountOutMin,
address to,
uint256 deadline
) external nonReentrant {
require(block.timestamp <= deadline, "Expired");
_swapPDAIForPLSInternal(amountIn, amountOutMin, to);
}
function _swapPDAIForPLSInternal(
uint256 amountIn,
uint256 amountOutMin,
address to
) internal {
uint256 balBefore = IERC20(pdai).balanceOf(address(this));
IERC20(pdai).safeTransferFrom(msg.sender, address(this), amountIn);
uint256 received = IERC20(pdai).balanceOf(address(this)) - balBefore;
uint256 feeAmt = (received * FEE_BPS) / BPS_BASE;
uint256 swapAmount = received - feeAmt;
_accumulateFee(feeAmt);
(uint256 rIn, uint256 rOut) = _getReserves(pdai);
uint256 wplsOut = _getAmountOut(swapAmount, rIn, rOut);
require(wplsOut >= amountOutMin, "Slippage");
bool pdaiIsT0 = IUniswapV2Pair(plsPdaiPair).token0() == pdai;
IERC20(pdai).safeTransfer(plsPdaiPair, swapAmount);
IUniswapV2Pair(plsPdaiPair).swap(
pdaiIsT0 ? 0 : wplsOut,
pdaiIsT0 ? wplsOut : 0,
address(this), bytes("")
);
_unwrapAndSendPLS(to);
emit SwapExecuted(msg.sender, pdai, address(0), amountIn, feeAmt);
}
function _unwrapAndSendPLS(address to) internal {
uint256 plsBalBefore = address(this).balance;
uint256 wplsBalance = IERC20(wpls).balanceOf(address(this));
(bool ok,) = wpls.call(abi.encodeWithSignature("withdraw(uint256)", wplsBalance));
require(ok, "WPLS unwrap failed");
uint256 plsReceived = address(this).balance - plsBalBefore;
(bool sent,) = to.call{value: plsReceived}("");
require(sent, "PLS send failed");
}
// ─────────────────────────────────────────────────────────────────────────
// GENERIC TOKEN TO TOKEN VIA MULTI HOP
// ─────────────────────────────────────────────────────────────────────────
function swapTokensMultiHop(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external nonReentrant {
require(path.length >= 3, "Need multi hop path");
SwapCache memory v;
v.tokenIn = path[0];
v.tokenOut = path[path.length - 1];
uint256 balBefore = IERC20(v.tokenIn).balanceOf(address(this));
IERC20(v.tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);
v.swapAmount = IERC20(v.tokenIn).balanceOf(address(this)) - balBefore;
if (v.tokenIn == pdai) {
v.feeAmt = (v.swapAmount * FEE_BPS) / BPS_BASE;
v.swapAmount -= v.feeAmt;
_accumulateFee(v.feeAmt);
}
v.pdaiBalBefore = (v.tokenOut == pdai) ? IERC20(pdai).balanceOf(address(this)) : 0;
_executeRouterSwap(v.swapAmount, amountOutMin, path, to, deadline, v.tokenOut == pdai);
if (v.tokenOut == pdai) {
uint256 pdaiOut = IERC20(pdai).balanceOf(address(this)) - v.pdaiBalBefore;
if (pdaiOut > 0) {
uint256 outDiv = (pdaiOut * FEE_BPS) / BPS_BASE;
v.feeAmt += outDiv;
_accumulateFee(outDiv);
IERC20(pdai).safeTransfer(to, pdaiOut - outDiv);
}
}
emit SwapExecuted(msg.sender, v.tokenIn, v.tokenOut, amountIn, v.feeAmt);
}
// ─────────────────────────────────────────────────────────────────────────
// INTERNAL & BUYBACK LOGIC
// ─────────────────────────────────────────────────────────────────────────
function _accumulateFee(uint256 amount) internal {
if (amount > 0) {
pendingBuyback += amount;
}
}
function flushBuyback() external nonReentrant {
uint256 amount = pendingBuyback;
require(amount >= MIN_BUYBURN, "Below minimum");
pendingBuyback = 0;
address[] memory path = new address[](2);
path[0] = pdai;
path[1] = pmintToken;
uint256 pmintBefore = IERC20(pmintToken).balanceOf(address(this));
IERC20(pdai).approve(pulseXRouter, amount);
IUniswapV2Router(pulseXRouter).swapExactTokensForTokensSupportingFeeOnTransferTokens(
amount,
0,
path,
address(this),
block.timestamp
);
IERC20(pdai).approve(pulseXRouter, 0);
uint256 pmintReceived = IERC20(pmintToken).balanceOf(address(this)) - pmintBefore;
if (pmintReceived > 0) {
IERC20(pmintToken).safeTransfer(BURN_ADDR, pmintReceived);
}
emit BuyBurnExecuted(amount, pmintReceived);
}
receive() external payable {}
}