Address
0x3be75c97b18d97125444fd503e79b25be475a3b8Current Holdings
$438.92
TXs sent
0
First Active
2026-06-01
block 26,677,144
Last Active
today
block 27,521,538
Net worth historyi
585 snapshots · to block 27,521,087coverage change 26 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Aug
exact matchPMINTSwapFeeRoutersolc 0.8.20+commit.a1b79de6runtime exact · creation exact
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/*
PMINTSwapFeeRouter
==================
*/
interface IERC20 {
function transfer(address to, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
function approve(address spender, uint256 value) external returns (bool);
}
contract PMINTSwapFeeRouter {
address public constant NATIVE = address(0);
uint256 public constant BPS_BASE = 10000;
uint256 public constant MAX_FEE_BPS = 100; // 1 percent hard ceiling, owner can never exceed
address public owner;
address public feeWallet;
uint256 public feeBps = 30; // 0.3 percent
mapping(address => bool) public allowedRouter;
uint256 private _lock = 1;
event SwapExecuted(address indexed user, address tokenIn, address router, uint256 amountIn, uint256 amountSwapped, uint256 feeAmount);
event RouterSet(address indexed router, bool allowed);
event FeeWalletSet(address indexed wallet);
event FeeBpsSet(uint256 bps);
event OwnerSet(address indexed owner);
modifier onlyOwner() { require(msg.sender == owner, "not owner"); _; }
modifier nonReentrant() { require(_lock == 1, "reentrant"); _lock = 2; _; _lock = 1; }
constructor(address _feeWallet, address[] memory _routers) {
require(_feeWallet != address(0), "fee wallet zero");
owner = msg.sender;
feeWallet = _feeWallet;
emit OwnerSet(msg.sender);
emit FeeWalletSet(_feeWallet);
for (uint256 i = 0; i < _routers.length; i++) {
require(_routers[i] != address(0), "router zero");
allowedRouter[_routers[i]] = true;
emit RouterSet(_routers[i], true);
}
}
// ----------------------------- swap -----------------------------
// tokenIn : input token, or address(0) for native PLS
// amountIn : total the user spends (must equal msg.value when native)
// router : the venue to call, must be allowlisted (PulseX or Piteas)
// data : swap calldata built by the frontend for (amountIn - fee),
// with the output recipient set to the user
function swap(
address tokenIn,
uint256 amountIn,
address router,
bytes calldata data
) external payable nonReentrant {
require(allowedRouter[router], "router not allowed");
require(amountIn > 0, "amount zero");
uint256 fee = (amountIn * feeBps) / BPS_BASE;
uint256 netIn = amountIn - fee;
require(netIn > 0, "net zero");
if (tokenIn == NATIVE) {
require(msg.value == amountIn, "bad msg.value");
if (fee > 0) _sendNative(feeWallet, fee);
(bool ok, ) = router.call{value: netIn}(data);
require(ok, "router call failed");
} else {
require(msg.value == 0, "native not expected");
_safeTransferFrom(tokenIn, msg.sender, address(this), amountIn);
if (fee > 0) _safeTransfer(tokenIn, feeWallet, fee);
_safeApprove(tokenIn, router, 0);
_safeApprove(tokenIn, router, netIn);
(bool ok, ) = router.call(data);
require(ok, "router call failed");
_safeApprove(tokenIn, router, 0);
}
emit SwapExecuted(msg.sender, tokenIn, router, amountIn, netIn, fee);
}
// ------------------- admin (renounce to freeze) -------------------
function setOwner(address o) external onlyOwner { owner = o; emit OwnerSet(o); }
function renounceOwnership() external onlyOwner { owner = address(0); emit OwnerSet(address(0)); }
function setFeeWallet(address w) external onlyOwner { require(w != address(0), "zero"); feeWallet = w; emit FeeWalletSet(w); }
function setFeeBps(uint256 b) external onlyOwner { require(b <= MAX_FEE_BPS, "fee too high"); feeBps = b; emit FeeBpsSet(b); }
function setRouter(address r, bool ok) external onlyOwner { require(r != address(0), "zero"); allowedRouter[r] = ok; emit RouterSet(r, ok); }
// ---- rescue (config only owner power; nothing sits here in normal use) ----
function rescue(address token, address to, uint256 amount) external onlyOwner {
require(to != address(0), "zero");
if (token == NATIVE) _sendNative(to, amount);
else _safeTransfer(token, to, amount);
}
// ----------------------------- helpers -----------------------------
function _sendNative(address to, uint256 amount) internal {
(bool ok, ) = to.call{value: amount}("");
require(ok, "native send failed");
}
function _safeTransfer(address token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(IERC20.transfer.selector, to, value));
}
function _safeTransferFrom(address token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));
}
function _safeApprove(address token, address spender, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(IERC20.approve.selector, spender, value));
}
function _callOptionalReturn(address token, bytes memory data) internal {
(bool ok, bytes memory ret) = token.call(data);
require(ok && (ret.length == 0 || abi.decode(ret, (bool))), "erc20 op failed");
}
receive() external payable {}
}