Address
0xfa97ff17165d2b9aec5bf8bbdab9a14fb00f5db8Current Holdings
$5.12
TXs sent
0
First Active
2026-04-12
block 26,266,820
Last Active
today
block 27,518,574
Net worth historyi
383 snapshots · to block 27,518,575coverage change 26 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Aug
exact matchbananasolc 0.8.34+commit.80d5c536runtime exact · creation exact
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
interface IWPLS {
function deposit() external payable;
function withdraw(uint256) external;
function balanceOf(address) external view returns (uint256);
}
interface IPLSXRouter {
function WETH9() external view returns (address);
function swapExactTokensForTokensV2(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to
) external payable returns (uint256 amountOut);
}
contract banana is ReentrancyGuard {
using SafeERC20 for IERC20;
address public owner;
IPLSXRouter public router;
IERC20 public token;
IWPLS public wpls;
uint256 public blockInterval;
uint256 public minPLSAmount;
uint256 public maxPLSAmount;
uint256 public lastActionBlock;
bool public isBuying = true;
bool public isPaused = false;
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_;
}
modifier onlyWhenRunning() {
require(!isPaused, "Paused");
_;
}
event BuyExecuted(uint256 plsIn, uint256 tokenOut);
event SellExecuted(uint256 tokenIn, uint256 plsOut);
constructor(
address _router,
address _token,
uint256 _interval,
uint256 _minPLS,
uint256 _maxPLS
) payable {
require(_minPLS > 0 && _maxPLS >= _minPLS, "Invalid range");
owner = msg.sender;
router = IPLSXRouter(_router);
token = IERC20(_token);
address _wpls = router.WETH9();
wpls = IWPLS(_wpls);
blockInterval = _interval;
minPLSAmount = _minPLS;
maxPLSAmount = _maxPLS;
lastActionBlock = block.number;
isBuying = true;
IERC20(_wpls).approve(_router, type(uint256).max);
token.approve(_router, type(uint256).max);
}
receive() external payable {}
// =========================
// RANDOM GENERATOR
// =========================
function _getRandomPLSAmount() internal view returns (uint256) {
if (minPLSAmount == maxPLSAmount) return minPLSAmount;
uint256 rand = uint256(
keccak256(
abi.encodePacked(
blockhash(block.number - 1),
block.timestamp,
address(this),
lastActionBlock
)
)
);
uint256 range = maxPLSAmount - minPLSAmount + 1;
return minPLSAmount + (rand % range);
}
// =========================
// CORE
// =========================
function checkAndAct() public onlyWhenRunning nonReentrant {
require(block.number >= lastActionBlock + blockInterval, "Too soon");
lastActionBlock = block.number;
if (isBuying) {
_buy();
} else {
_sell();
}
isBuying = !isBuying;
}
// =========================
// BUY (RANDOMIZED SIZE)
// =========================
function _buy() internal {
uint256 amountPLS = _getRandomPLSAmount();
require(address(this).balance >= amountPLS, "NO_PLS");
uint256 beforeBal = wpls.balanceOf(address(this));
wpls.deposit{value: amountPLS}();
uint256 afterBal = wpls.balanceOf(address(this));
require(afterBal > beforeBal, "WRAP_FAILED");
address[] memory path = new address[](2);
path[0] = address(wpls);
path[1] = address(token);
uint256 tokenBefore = token.balanceOf(address(this));
uint256 amountOut = router.swapExactTokensForTokensV2(
amountPLS,
1,
path,
address(this)
);
uint256 tokenAfter = token.balanceOf(address(this));
require(tokenAfter > tokenBefore, "SWAP_FAILED");
emit BuyExecuted(amountPLS, amountOut);
}
// =========================
// SELL (ALL TOKENS)
// =========================
function _sell() internal {
uint256 balance = token.balanceOf(address(this));
require(balance > 0, "NO_TOKEN");
address[] memory path = new address[](2);
path[0] = address(token);
path[1] = address(wpls);
uint256 wplsBefore = wpls.balanceOf(address(this));
uint256 amountOut = router.swapExactTokensForTokensV2(
balance,
1,
path,
address(this)
);
uint256 wplsAfter = wpls.balanceOf(address(this));
require(wplsAfter > wplsBefore, "SELL_SWAP_FAILED");
wpls.withdraw(wplsAfter);
emit SellExecuted(balance, amountOut);
}
// =========================
// ADMIN
// =========================
function setRange(uint256 _min, uint256 _max) external onlyOwner {
require(_min > 0 && _max >= _min, "Invalid range");
minPLSAmount = _min;
maxPLSAmount = _max;
}
function withdrawPLS(uint256 amount) external onlyOwner {
require(address(this).balance >= amount, "Insufficient");
(bool success, ) = owner.call{value: amount}("");
require(success, "Transfer failed");
}
function unwrapAndWithdrawWPLS() external onlyOwner {
uint256 bal = wpls.balanceOf(address(this));
wpls.withdraw(bal);
(bool success, ) = owner.call{value: address(this).balance}("");
require(success, "Transfer failed");
}
function withdrawToken() external onlyOwner {
token.safeTransfer(owner, token.balanceOf(address(this)));
}
function pause() external onlyOwner {
isPaused = true;
}
function unpause() external onlyOwner {
isPaused = false;
}
// Add these functions to your contract
function getPLSBalance() public view returns (uint256) {
return address(this).balance;
}
function getWPLSBalance() public view returns (uint256) {
return wpls.balanceOf(address(this));
}
function getTokenBalance() public view returns (uint256) {
return token.balanceOf(address(this));
}
}