Created
September 16, 2025 05:16
-
-
Save Vicky7830/16f15e793dc006ebe3a861b50cb11355 to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.8.25+commit.b61c2a91.js&optimize=false&runs=200&gist=
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.30; | |
| interface IERC20 { | |
| event Transfer(address indexed from, address indexed to, uint256 value); | |
| event Approval(address indexed owner, address indexed spender, uint256 value); | |
| function totalSupply() external view returns (uint256); | |
| function balanceOf(address account) external view returns (uint256); | |
| function transfer(address to, 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 from, | |
| address to, | |
| uint256 amount | |
| ) external returns (bool); | |
| } | |
| abstract contract Context { | |
| function _msgSender() internal view virtual returns (address) { | |
| return msg.sender; | |
| } | |
| function _msgData() internal view virtual returns (bytes calldata) { | |
| return msg.data; | |
| } | |
| } | |
| abstract contract Ownable is Context { | |
| address private _owner; | |
| event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); | |
| constructor() { | |
| _transferOwnership(_msgSender()); | |
| } | |
| function owner() public view virtual returns (address) { | |
| return _owner; | |
| } | |
| modifier onlyOwner() { | |
| require(owner() == _msgSender(), "Ownable: caller is not the owner"); | |
| _; | |
| } | |
| function renounceOwnership() public virtual onlyOwner { | |
| _transferOwnership(address(0)); | |
| } | |
| function transferOwnership(address newOwner) public virtual onlyOwner { | |
| require(newOwner != address(0), "Ownable: new owner is the zero address"); | |
| _transferOwnership(newOwner); | |
| } | |
| function _transferOwnership(address newOwner) internal virtual { | |
| address oldOwner = _owner; | |
| _owner = newOwner; | |
| emit OwnershipTransferred(oldOwner, newOwner); | |
| } | |
| } | |
| library SafeMath { | |
| function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { | |
| unchecked { | |
| uint256 c = a + b; | |
| if (c < a) return (false, 0); | |
| return (true, c); | |
| } | |
| } | |
| function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { | |
| unchecked { | |
| if (b > a) return (false, 0); | |
| return (true, a - b); | |
| } | |
| } | |
| function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { | |
| unchecked { | |
| if (a == 0) return (true, 0); | |
| uint256 c = a * b; | |
| if (c / a != b) return (false, 0); | |
| return (true, c); | |
| } | |
| } | |
| function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { | |
| unchecked { | |
| if (b == 0) return (false, 0); | |
| return (true, a / b); | |
| } | |
| } | |
| function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { | |
| unchecked { | |
| if (b == 0) return (false, 0); | |
| return (true, a % b); | |
| } | |
| } | |
| function add(uint256 a, uint256 b) internal pure returns (uint256) { | |
| return a + b; | |
| } | |
| function sub(uint256 a, uint256 b) internal pure returns (uint256) { | |
| return a - b; | |
| } | |
| function mul(uint256 a, uint256 b) internal pure returns (uint256) { | |
| return a * b; | |
| } | |
| function div(uint256 a, uint256 b) internal pure returns (uint256) { | |
| return a / b; | |
| } | |
| function mod(uint256 a, uint256 b) internal pure returns (uint256) { | |
| return a % b; | |
| } | |
| function sub( | |
| uint256 a, | |
| uint256 b, | |
| string memory errorMessage | |
| ) internal pure returns (uint256) { | |
| unchecked { | |
| require(b <= a, errorMessage); | |
| return a - b; | |
| } | |
| } | |
| function div( | |
| uint256 a, | |
| uint256 b, | |
| string memory errorMessage | |
| ) internal pure returns (uint256) { | |
| unchecked { | |
| require(b > 0, errorMessage); | |
| return a / b; | |
| } | |
| } | |
| function mod( | |
| uint256 a, | |
| uint256 b, | |
| string memory errorMessage | |
| ) internal pure returns (uint256) { | |
| unchecked { | |
| require(b > 0, errorMessage); | |
| return a % b; | |
| } | |
| } | |
| } | |
| library Address { | |
| function isContract(address account) internal view returns (bool) { | |
| return account.code.length > 0; | |
| } | |
| function sendValue(address payable recipient, uint256 amount) internal { | |
| require(address(this).balance >= amount, "Address: insufficient balance"); | |
| (bool success, ) = recipient.call{value: amount}(""); | |
| require(success, "Address: unable to send value, recipient may have reverted"); | |
| } | |
| function functionCall(address target, bytes memory data) internal returns (bytes memory) { | |
| return functionCall(target, data, "Address: low-level call failed"); | |
| } | |
| function functionCall( | |
| address target, | |
| bytes memory data, | |
| string memory errorMessage | |
| ) internal returns (bytes memory) { | |
| return functionCallWithValue(target, data, 0, errorMessage); | |
| } | |
| function functionCallWithValue( | |
| address target, | |
| bytes memory data, | |
| uint256 value | |
| ) internal returns (bytes memory) { | |
| return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); | |
| } | |
| function functionCallWithValue( | |
| address target, | |
| bytes memory data, | |
| uint256 value, | |
| string memory errorMessage | |
| ) internal returns (bytes memory) { | |
| require(address(this).balance >= value, "Address: insufficient balance for call"); | |
| require(isContract(target), "Address: call to non-contract"); | |
| (bool success, bytes memory returndata) = target.call{value: value}(data); | |
| return verifyCallResult(success, returndata, errorMessage); | |
| } | |
| function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { | |
| return functionStaticCall(target, data, "Address: low-level static call failed"); | |
| } | |
| function functionStaticCall( | |
| address target, | |
| bytes memory data, | |
| string memory errorMessage | |
| ) internal view returns (bytes memory) { | |
| require(isContract(target), "Address: static call to non-contract"); | |
| (bool success, bytes memory returndata) = target.staticcall(data); | |
| return verifyCallResult(success, returndata, errorMessage); | |
| } | |
| function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { | |
| return functionDelegateCall(target, data, "Address: low-level delegate call failed"); | |
| } | |
| function functionDelegateCall( | |
| address target, | |
| bytes memory data, | |
| string memory errorMessage | |
| ) internal returns (bytes memory) { | |
| require(isContract(target), "Address: delegate call to non-contract"); | |
| (bool success, bytes memory returndata) = target.delegatecall(data); | |
| return verifyCallResult(success, returndata, errorMessage); | |
| } | |
| function verifyCallResult( | |
| bool success, | |
| bytes memory returndata, | |
| string memory errorMessage | |
| ) internal pure returns (bytes memory) { | |
| if (success) { | |
| return returndata; | |
| } else { | |
| if (returndata.length > 0) { | |
| assembly { | |
| let returndata_size := mload(returndata) | |
| revert(add(32, returndata), returndata_size) | |
| } | |
| } else { | |
| revert(errorMessage); | |
| } | |
| } | |
| } | |
| } | |
| library SafeERC20 { | |
| using Address for address; | |
| function safeTransfer( | |
| IERC20 token, | |
| address to, | |
| uint256 value | |
| ) internal { | |
| _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); | |
| } | |
| function safeTransferFrom( | |
| IERC20 token, | |
| address from, | |
| address to, | |
| uint256 value | |
| ) internal { | |
| _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); | |
| } | |
| function safeApprove( | |
| IERC20 token, | |
| address spender, | |
| uint256 value | |
| ) internal { | |
| require( | |
| (value == 0) || (token.allowance(address(this), spender) == 0), | |
| "SafeERC20: approve from non-zero to non-zero allowance" | |
| ); | |
| _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); | |
| } | |
| function safeIncreaseAllowance( | |
| IERC20 token, | |
| address spender, | |
| uint256 value | |
| ) internal { | |
| uint256 newAllowance = token.allowance(address(this), spender) + value; | |
| _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); | |
| } | |
| function safeDecreaseAllowance( | |
| IERC20 token, | |
| address spender, | |
| uint256 value | |
| ) internal { | |
| unchecked { | |
| uint256 oldAllowance = token.allowance(address(this), spender); | |
| require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); | |
| uint256 newAllowance = oldAllowance - value; | |
| _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); | |
| } | |
| } | |
| function _callOptionalReturn(IERC20 token, bytes memory data) private { | |
| bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); | |
| if (returndata.length > 0) { | |
| // Return data is optional | |
| require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); | |
| } | |
| } | |
| } | |
| interface IRouter { | |
| function swapExactTokensForTokens( | |
| uint256 amountIn, | |
| uint256 amountOutMin, | |
| address[] calldata path, | |
| address to, | |
| uint256 deadline | |
| ) external returns (uint256[] memory amounts); | |
| function swapExactETHForTokens( | |
| uint256 amountOutMin, | |
| address[] calldata path, | |
| address to, | |
| uint256 deadline | |
| ) external payable returns (uint256[] memory amounts); | |
| function swapExactTokensForETH( | |
| uint256 amountIn, | |
| uint256 amountOutMin, | |
| address[] calldata path, | |
| address to, | |
| uint256 deadline | |
| ) external returns (uint256[] memory amounts); | |
| function getAmountsOut(uint256 amountIn, address[] calldata path) | |
| external | |
| view | |
| returns (uint256[] memory amounts); | |
| } | |
| contract Gswap is Ownable { | |
| using SafeMath for uint256; | |
| using SafeERC20 for IERC20; | |
| uint public feePercent = 1; // 0.001% | |
| // ✅ Swap storage | |
| struct SwapDetail { | |
| address user; | |
| address tokenA; | |
| address tokenB; | |
| uint256 amountIn; | |
| address[] path; | |
| } | |
| mapping(uint256 => SwapDetail) public swaps; | |
| event CustomSwapExecuted( | |
| uint256 indexed swapId, | |
| address indexed user, | |
| address tokenA, | |
| address tokenB, | |
| uint256 amountIn, | |
| address[] path | |
| ); | |
| address public feeAccount; | |
| address public router; | |
| address public wbnb; | |
| mapping(address => bool) public whitelistedTokens; | |
| constructor(address _feeAccount, address _router, address _wbnb) { | |
| feeAccount = _feeAccount; | |
| router = _router; | |
| wbnb = _wbnb; | |
| } | |
| function swapTokens(address _tokenA, address _tokenB, uint256 _amountIn) external payable { | |
| address[] memory path = new address[](2); | |
| if (_tokenA == address(0)) { | |
| path[0] = wbnb; | |
| path[1] = _tokenB; | |
| } else if (_tokenB == address(0)) { | |
| path[0] = _tokenA; | |
| path[1] = wbnb; | |
| } else { | |
| path[0] = _tokenA; | |
| path[1] = _tokenB; | |
| } | |
| _proceedToUniswap(_tokenA, _tokenB, _amountIn, path); | |
| } | |
| function customSwapTokens( uint256 swapId,address _tokenA, address _tokenB, uint256 _amountIn, address[]memory path) external payable{ | |
| if (_tokenA == address(0)) { | |
| require(wbnb == path[0] && _tokenB == path[path.length - 1], "SoleriumSWAP: Path must be specified"); | |
| } else if (_tokenB == address(0)) { | |
| require(_tokenA == path[0] && wbnb == path[path.length - 1], "SoleriumSWAP: Path must be specified"); | |
| } else { | |
| require(_tokenA == path[0] && _tokenB == path[path.length - 1], "SoleriumSWAP: Path must be specified"); | |
| } | |
| _proceedToUniswap(_tokenA, _tokenB, _amountIn, path); | |
| swaps[swapId] = SwapDetail(msg.sender, _tokenA, _tokenB, _amountIn, path); | |
| emit CustomSwapExecuted(swapId, msg.sender, _tokenA, _tokenB, _amountIn, path); | |
| } | |
| function _proceedToUniswap(address _tokenA, address _tokenB, uint256 _amountIn, address[]memory path) internal { | |
| require(_amountIn > 0, "SoleriumSWAP: amountIn must be greater than 0"); | |
| require(whitelistedTokens[_tokenA], "SoleriumSWAP: TokenA is not whitelisted"); | |
| if (_tokenA == address(0)) { | |
| require (_amountIn >= msg.value, "SoleriumSWAP: Insufficient ETH"); | |
| uint fee = _amountIn * feePercent / 100000; | |
| payable(feeAccount).transfer(fee); | |
| uint amountToSwap = _amountIn - fee; | |
| _swapBNBForTokens(amountToSwap, path); | |
| } else{ | |
| IERC20(_tokenA).safeTransferFrom(msg.sender, address(this), _amountIn); | |
| uint fee = _amountIn * feePercent / 100000; | |
| IERC20(_tokenA).safeTransfer(feeAccount, fee); | |
| uint amountToSwap = _amountIn - fee; | |
| if (_tokenB == address(0)) { | |
| _swapTokensForBNB(amountToSwap, path); | |
| } else { | |
| _swapTokensForTokens(amountToSwap, path); | |
| } | |
| } | |
| } | |
| function _approve(address _token, uint _amount) internal { | |
| IERC20(_token).approve(address(router), _amount); | |
| } | |
| function _swapTokensForBNB(uint _amount, address[]memory path) internal { | |
| IRouter(router).swapExactTokensForETH( | |
| _amount, | |
| 0, | |
| path, | |
| msg.sender, | |
| block.timestamp | |
| ); | |
| } | |
| function _swapBNBForTokens(uint _amount, address[]memory path) internal { | |
| IRouter(router).swapExactETHForTokens{ value: _amount }( | |
| 0, | |
| path, | |
| msg.sender, | |
| block.timestamp | |
| ); | |
| } | |
| function _swapTokensForTokens(uint _amount, address[]memory path) internal { | |
| IRouter(router).swapExactTokensForTokens( | |
| _amount, | |
| 0, | |
| path, | |
| msg.sender, | |
| block.timestamp | |
| ); | |
| } | |
| function getOutputTokenAmount(uint inputAmount, address[]memory path) external view returns (uint outputAmount) { | |
| uint[]memory outputs = IRouter(router).getAmountsOut(inputAmount, path); | |
| return outputs[outputs.length - 1]; | |
| } | |
| function setFeePercent(uint _feePercent) external onlyOwner { | |
| feePercent = _feePercent; | |
| } | |
| function setFeeAccount(address _feeAccount) external onlyOwner { | |
| feeAccount = _feeAccount; | |
| } | |
| function setRouterWBNB(address _router, address _wbnb) external onlyOwner { | |
| router = _router; | |
| wbnb = _wbnb; | |
| } | |
| function addWhitelistedTokens(address[]memory _tokens) external onlyOwner { | |
| for (uint i = 0; i < _tokens.length; i++) { | |
| whitelistedTokens[_tokens[i]] = true; | |
| if (_tokens[i] != address(0)) { | |
| _approve(_tokens[i], type(uint256).max); | |
| } | |
| } | |
| } | |
| function removeWhitelistedTokens(address[]memory _tokens) external onlyOwner { | |
| for (uint i = 0; i < _tokens.length; i++) { | |
| whitelistedTokens[_tokens[i]] = false; | |
| } | |
| } | |
| function approveTokens(address[]memory _tokens, uint[] memory _amounts) external onlyOwner { | |
| for (uint i = 0; i < _tokens.length; i++) { | |
| _approve(_tokens[i], _amounts[i]); | |
| } | |
| } | |
| function emergencyWithdraw(address _token, uint _amount) external onlyOwner { | |
| IERC20(_token).safeTransfer(msg.sender, _amount); | |
| } | |
| function emergencyWithdrawETH(uint _amount) external onlyOwner { | |
| payable(owner()).transfer(_amount); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: GPL-3.0 | |
| pragma solidity >=0.7.0 <0.9.0; | |
| import "hardhat/console.sol"; | |
| /** | |
| * @title Owner | |
| * @dev Set & change owner | |
| */ | |
| contract Owner { | |
| address private owner; | |
| // event for EVM logging | |
| event OwnerSet(address indexed oldOwner, address indexed newOwner); | |
| // modifier to check if caller is owner | |
| modifier isOwner() { | |
| // If the first argument of 'require' evaluates to 'false', execution terminates and all | |
| // changes to the state and to Ether balances are reverted. | |
| // This used to consume all gas in old EVM versions, but not anymore. | |
| // It is often a good idea to use 'require' to check if functions are called correctly. | |
| // As a second argument, you can also provide an explanation about what went wrong. | |
| require(msg.sender == owner, "Caller is not owner"); | |
| _; | |
| } | |
| /** | |
| * @dev Set contract deployer as owner | |
| */ | |
| constructor() { | |
| console.log("Owner contract deployed by:", msg.sender); | |
| owner = msg.sender; // 'msg.sender' is sender of current call, contract deployer for a constructor | |
| emit OwnerSet(address(0), owner); | |
| } | |
| /** | |
| * @dev Change owner | |
| * @param newOwner address of new owner | |
| */ | |
| function changeOwner(address newOwner) public isOwner { | |
| require(newOwner != address(0), "New owner should not be the zero address"); | |
| emit OwnerSet(owner, newOwner); | |
| owner = newOwner; | |
| } | |
| /** | |
| * @dev Return owner address | |
| * @return address of owner | |
| */ | |
| function getOwner() external view returns (address) { | |
| return owner; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: GPL-3.0 | |
| pragma solidity >=0.7.0 <0.9.0; | |
| /** | |
| * @title Ballot | |
| * @dev Implements voting process along with vote delegation | |
| */ | |
| contract Ballot { | |
| // This declares a new complex type which will | |
| // be used for variables later. | |
| // It will represent a single voter. | |
| struct Voter { | |
| uint weight; // weight is accumulated by delegation | |
| bool voted; // if true, that person already voted | |
| address delegate; // person delegated to | |
| uint vote; // index of the voted proposal | |
| } | |
| // This is a type for a single proposal. | |
| struct Proposal { | |
| // If you can limit the length to a certain number of bytes, | |
| // always use one of bytes1 to bytes32 because they are much cheaper | |
| bytes32 name; // short name (up to 32 bytes) | |
| uint voteCount; // number of accumulated votes | |
| } | |
| address public chairperson; | |
| // This declares a state variable that | |
| // stores a 'Voter' struct for each possible address. | |
| mapping(address => Voter) public voters; | |
| // A dynamically-sized array of 'Proposal' structs. | |
| Proposal[] public proposals; | |
| /** | |
| * @dev Create a new ballot to choose one of 'proposalNames'. | |
| * @param proposalNames names of proposals | |
| */ | |
| constructor(bytes32[] memory proposalNames) { | |
| chairperson = msg.sender; | |
| voters[chairperson].weight = 1; | |
| // For each of the provided proposal names, | |
| // create a new proposal object and add it | |
| // to the end of the array. | |
| for (uint i = 0; i < proposalNames.length; i++) { | |
| // 'Proposal({...})' creates a temporary | |
| // Proposal object and 'proposals.push(...)' | |
| // appends it to the end of 'proposals'. | |
| proposals.push(Proposal({ | |
| name: proposalNames[i], | |
| voteCount: 0 | |
| })); | |
| } | |
| } | |
| /** | |
| * @dev Give 'voter' the right to vote on this ballot. May only be called by 'chairperson'. | |
| * @param voter address of voter | |
| */ | |
| function giveRightToVote(address voter) external { | |
| // If the first argument of `require` evaluates | |
| // to 'false', execution terminates and all | |
| // changes to the state and to Ether balances | |
| // are reverted. | |
| // This used to consume all gas in old EVM versions, but | |
| // not anymore. | |
| // It is often a good idea to use 'require' to check if | |
| // functions are called correctly. | |
| // As a second argument, you can also provide an | |
| // explanation about what went wrong. | |
| require( | |
| msg.sender == chairperson, | |
| "Only chairperson can give right to vote." | |
| ); | |
| require( | |
| !voters[voter].voted, | |
| "The voter already voted." | |
| ); | |
| require(voters[voter].weight == 0, "Voter already has the right to vote."); | |
| voters[voter].weight = 1; | |
| } | |
| /** | |
| * @dev Delegate your vote to the voter 'to'. | |
| * @param to address to which vote is delegated | |
| */ | |
| function delegate(address to) external { | |
| // assigns reference | |
| Voter storage sender = voters[msg.sender]; | |
| require(sender.weight != 0, "You have no right to vote"); | |
| require(!sender.voted, "You already voted."); | |
| require(to != msg.sender, "Self-delegation is disallowed."); | |
| // Forward the delegation as long as | |
| // 'to' also delegated. | |
| // In general, such loops are very dangerous, | |
| // because if they run too long, they might | |
| // need more gas than is available in a block. | |
| // In this case, the delegation will not be executed, | |
| // but in other situations, such loops might | |
| // cause a contract to get "stuck" completely. | |
| while (voters[to].delegate != address(0)) { | |
| to = voters[to].delegate; | |
| // We found a loop in the delegation, not allowed. | |
| require(to != msg.sender, "Found loop in delegation."); | |
| } | |
| Voter storage delegate_ = voters[to]; | |
| // Voters cannot delegate to accounts that cannot vote. | |
| require(delegate_.weight >= 1); | |
| // Since 'sender' is a reference, this | |
| // modifies 'voters[msg.sender]'. | |
| sender.voted = true; | |
| sender.delegate = to; | |
| if (delegate_.voted) { | |
| // If the delegate already voted, | |
| // directly add to the number of votes | |
| proposals[delegate_.vote].voteCount += sender.weight; | |
| } else { | |
| // If the delegate did not vote yet, | |
| // add to her weight. | |
| delegate_.weight += sender.weight; | |
| } | |
| } | |
| /** | |
| * @dev Give your vote (including votes delegated to you) to proposal 'proposals[proposal].name'. | |
| * @param proposal index of proposal in the proposals array | |
| */ | |
| function vote(uint proposal) external { | |
| Voter storage sender = voters[msg.sender]; | |
| require(sender.weight != 0, "Has no right to vote"); | |
| require(!sender.voted, "Already voted."); | |
| sender.voted = true; | |
| sender.vote = proposal; | |
| // If 'proposal' is out of the range of the array, | |
| // this will throw automatically and revert all | |
| // changes. | |
| proposals[proposal].voteCount += sender.weight; | |
| } | |
| /** | |
| * @dev Computes the winning proposal taking all previous votes into account. | |
| * @return winningProposal_ index of winning proposal in the proposals array | |
| */ | |
| function winningProposal() public view | |
| returns (uint winningProposal_) | |
| { | |
| uint winningVoteCount = 0; | |
| for (uint p = 0; p < proposals.length; p++) { | |
| if (proposals[p].voteCount > winningVoteCount) { | |
| winningVoteCount = proposals[p].voteCount; | |
| winningProposal_ = p; | |
| } | |
| } | |
| } | |
| /** | |
| * @dev Calls winningProposal() function to get the index of the winner contained in the proposals array and then | |
| * @return winnerName_ the name of the winner | |
| */ | |
| function winnerName() external view | |
| returns (bytes32 winnerName_) | |
| { | |
| winnerName_ = proposals[winningProposal()].name; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.30; | |
| interface IERC20 { | |
| function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
| function transfer(address recipient, uint256 amount) external returns (bool); | |
| function balanceOf(address account) external view returns (uint256); | |
| } | |
| contract HASHORAPool { | |
| address public owner; | |
| IERC20 public hashora; | |
| struct DepositInfo { | |
| uint256 amount; | |
| uint256 timestamp; | |
| } | |
| // Mapping: user => total deposit | |
| mapping(address => DepositInfo[]) public deposits; | |
| event Deposited(address indexed from, address indexed to, uint256 amount); | |
| event Withdrawn(address indexed owner, uint256 amount); | |
| event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); | |
| modifier onlyOwner() { | |
| require(msg.sender == owner, "Not owner"); | |
| _; | |
| } | |
| constructor(address _hashora) { | |
| owner = msg.sender; // contract deployer is owner | |
| hashora = IERC20(_hashora); // hashora token address | |
| emit OwnershipTransferred(address(0), owner); | |
| } | |
| /// @notice Deposit hashora on behalf of another address | |
| function deposit(address to, uint256 amount) external { | |
| require(to != address(0), "Invalid recipient"); | |
| require(amount > 0, "Amount must be > 0"); | |
| require(hashora.transferFrom(msg.sender, address(this), amount), "hashora transfer failed"); | |
| deposits[to].push(DepositInfo(amount, block.timestamp)); | |
| emit Deposited(msg.sender, to, amount); | |
| } | |
| /// @notice Withdraw hashora (only owner) | |
| function withdraw(uint256 amount) external onlyOwner { | |
| require(amount > 0, "Amount must be > 0"); | |
| require(hashora.balanceOf(address(this)) >= amount, "Insufficient balance"); | |
| require(hashora.transfer(owner, amount), "Withdraw failed"); | |
| emit Withdrawn(owner, amount); | |
| } | |
| /// @notice Contract's hashora balance | |
| function contractBalance() external view returns (uint256) { | |
| return hashora.balanceOf(address(this)); | |
| } | |
| /// @notice Get all deposits of a user | |
| function getUserDeposits(address user) external view returns (DepositInfo[] memory) { | |
| return deposits[user]; | |
| } | |
| /// @notice Transfer contract ownership | |
| function transferOwnership(address newOwner) external onlyOwner { | |
| require(newOwner != address(0), "Invalid new owner"); | |
| emit OwnershipTransferred(owner, newOwner); | |
| owner = newOwner; | |
| } | |
| /// @notice Renounce ownership (contract becomes ownerless) | |
| function renounceOwnership() external onlyOwner { | |
| emit OwnershipTransferred(owner, address(0)); | |
| owner = address(0); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| pragma solidity ^0.8.30; | |
| interface IERC20 { | |
| event Transfer(address indexed from, address indexed to, uint256 value); | |
| event Approval(address indexed owner, address indexed spender, uint256 value); | |
| function totalSupply() external view returns (uint256); | |
| function balanceOf(address account) external view returns (uint256); | |
| function transfer(address to, 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 from, | |
| address to, | |
| uint256 amount | |
| ) external returns (bool); | |
| } | |
| abstract contract Context { | |
| function _msgSender() internal view virtual returns (address) { | |
| return msg.sender; | |
| } | |
| function _msgData() internal view virtual returns (bytes calldata) { | |
| return msg.data; | |
| } | |
| } | |
| abstract contract Ownable is Context { | |
| address private _owner; | |
| event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); | |
| constructor() { | |
| _transferOwnership(_msgSender()); | |
| } | |
| function owner() public view virtual returns (address) { | |
| return _owner; | |
| } | |
| modifier onlyOwner() { | |
| require(owner() == _msgSender(), "Ownable: caller is not the owner"); | |
| _; | |
| } | |
| function renounceOwnership() public virtual onlyOwner { | |
| _transferOwnership(address(0)); | |
| } | |
| function transferOwnership(address newOwner) public virtual onlyOwner { | |
| require(newOwner != address(0), "Ownable: new owner is the zero address"); | |
| _transferOwnership(newOwner); | |
| } | |
| function _transferOwnership(address newOwner) internal virtual { | |
| address oldOwner = _owner; | |
| _owner = newOwner; | |
| emit OwnershipTransferred(oldOwner, newOwner); | |
| } | |
| } | |
| library SafeMath { | |
| function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { | |
| unchecked { | |
| uint256 c = a + b; | |
| if (c < a) return (false, 0); | |
| return (true, c); | |
| } | |
| } | |
| function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { | |
| unchecked { | |
| if (b > a) return (false, 0); | |
| return (true, a - b); | |
| } | |
| } | |
| function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { | |
| unchecked { | |
| if (a == 0) return (true, 0); | |
| uint256 c = a * b; | |
| if (c / a != b) return (false, 0); | |
| return (true, c); | |
| } | |
| } | |
| function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { | |
| unchecked { | |
| if (b == 0) return (false, 0); | |
| return (true, a / b); | |
| } | |
| } | |
| function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { | |
| unchecked { | |
| if (b == 0) return (false, 0); | |
| return (true, a % b); | |
| } | |
| } | |
| function add(uint256 a, uint256 b) internal pure returns (uint256) { | |
| return a + b; | |
| } | |
| function sub(uint256 a, uint256 b) internal pure returns (uint256) { | |
| return a - b; | |
| } | |
| function mul(uint256 a, uint256 b) internal pure returns (uint256) { | |
| return a * b; | |
| } | |
| function div(uint256 a, uint256 b) internal pure returns (uint256) { | |
| return a / b; | |
| } | |
| function mod(uint256 a, uint256 b) internal pure returns (uint256) { | |
| return a % b; | |
| } | |
| function sub( | |
| uint256 a, | |
| uint256 b, | |
| string memory errorMessage | |
| ) internal pure returns (uint256) { | |
| unchecked { | |
| require(b <= a, errorMessage); | |
| return a - b; | |
| } | |
| } | |
| function div( | |
| uint256 a, | |
| uint256 b, | |
| string memory errorMessage | |
| ) internal pure returns (uint256) { | |
| unchecked { | |
| require(b > 0, errorMessage); | |
| return a / b; | |
| } | |
| } | |
| function mod( | |
| uint256 a, | |
| uint256 b, | |
| string memory errorMessage | |
| ) internal pure returns (uint256) { | |
| unchecked { | |
| require(b > 0, errorMessage); | |
| return a % b; | |
| } | |
| } | |
| } | |
| library Address { | |
| function isContract(address account) internal view returns (bool) { | |
| return account.code.length > 0; | |
| } | |
| function sendValue(address payable recipient, uint256 amount) internal { | |
| require(address(this).balance >= amount, "Address: insufficient balance"); | |
| (bool success, ) = recipient.call{value: amount}(""); | |
| require(success, "Address: unable to send value, recipient may have reverted"); | |
| } | |
| function functionCall(address target, bytes memory data) internal returns (bytes memory) { | |
| return functionCall(target, data, "Address: low-level call failed"); | |
| } | |
| function functionCall( | |
| address target, | |
| bytes memory data, | |
| string memory errorMessage | |
| ) internal returns (bytes memory) { | |
| return functionCallWithValue(target, data, 0, errorMessage); | |
| } | |
| function functionCallWithValue( | |
| address target, | |
| bytes memory data, | |
| uint256 value | |
| ) internal returns (bytes memory) { | |
| return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); | |
| } | |
| function functionCallWithValue( | |
| address target, | |
| bytes memory data, | |
| uint256 value, | |
| string memory errorMessage | |
| ) internal returns (bytes memory) { | |
| require(address(this).balance >= value, "Address: insufficient balance for call"); | |
| require(isContract(target), "Address: call to non-contract"); | |
| (bool success, bytes memory returndata) = target.call{value: value}(data); | |
| return verifyCallResult(success, returndata, errorMessage); | |
| } | |
| function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { | |
| return functionStaticCall(target, data, "Address: low-level static call failed"); | |
| } | |
| function functionStaticCall( | |
| address target, | |
| bytes memory data, | |
| string memory errorMessage | |
| ) internal view returns (bytes memory) { | |
| require(isContract(target), "Address: static call to non-contract"); | |
| (bool success, bytes memory returndata) = target.staticcall(data); | |
| return verifyCallResult(success, returndata, errorMessage); | |
| } | |
| function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { | |
| return functionDelegateCall(target, data, "Address: low-level delegate call failed"); | |
| } | |
| function functionDelegateCall( | |
| address target, | |
| bytes memory data, | |
| string memory errorMessage | |
| ) internal returns (bytes memory) { | |
| require(isContract(target), "Address: delegate call to non-contract"); | |
| (bool success, bytes memory returndata) = target.delegatecall(data); | |
| return verifyCallResult(success, returndata, errorMessage); | |
| } | |
| function verifyCallResult( | |
| bool success, | |
| bytes memory returndata, | |
| string memory errorMessage | |
| ) internal pure returns (bytes memory) { | |
| if (success) { | |
| return returndata; | |
| } else { | |
| if (returndata.length > 0) { | |
| assembly { | |
| let returndata_size := mload(returndata) | |
| revert(add(32, returndata), returndata_size) | |
| } | |
| } else { | |
| revert(errorMessage); | |
| } | |
| } | |
| } | |
| } | |
| library SafeERC20 { | |
| using Address for address; | |
| function safeTransfer( | |
| IERC20 token, | |
| address to, | |
| uint256 value | |
| ) internal { | |
| _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); | |
| } | |
| function safeTransferFrom( | |
| IERC20 token, | |
| address from, | |
| address to, | |
| uint256 value | |
| ) internal { | |
| _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); | |
| } | |
| function safeApprove( | |
| IERC20 token, | |
| address spender, | |
| uint256 value | |
| ) internal { | |
| require( | |
| (value == 0) || (token.allowance(address(this), spender) == 0), | |
| "SafeERC20: approve from non-zero to non-zero allowance" | |
| ); | |
| _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); | |
| } | |
| function safeIncreaseAllowance( | |
| IERC20 token, | |
| address spender, | |
| uint256 value | |
| ) internal { | |
| uint256 newAllowance = token.allowance(address(this), spender) + value; | |
| _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); | |
| } | |
| function safeDecreaseAllowance( | |
| IERC20 token, | |
| address spender, | |
| uint256 value | |
| ) internal { | |
| unchecked { | |
| uint256 oldAllowance = token.allowance(address(this), spender); | |
| require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); | |
| uint256 newAllowance = oldAllowance - value; | |
| _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); | |
| } | |
| } | |
| function _callOptionalReturn(IERC20 token, bytes memory data) private { | |
| bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); | |
| if (returndata.length > 0) { | |
| // Return data is optional | |
| require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); | |
| } | |
| } | |
| } | |
| interface IRouter { | |
| function swapExactTokensForTokens( | |
| uint256 amountIn, | |
| uint256 amountOutMin, | |
| address[] calldata path, | |
| address to, | |
| uint256 deadline | |
| ) external returns (uint256[] memory amounts); | |
| function swapExactETHForTokens( | |
| uint256 amountOutMin, | |
| address[] calldata path, | |
| address to, | |
| uint256 deadline | |
| ) external payable returns (uint256[] memory amounts); | |
| function swapExactTokensForETH( | |
| uint256 amountIn, | |
| uint256 amountOutMin, | |
| address[] calldata path, | |
| address to, | |
| uint256 deadline | |
| ) external returns (uint256[] memory amounts); | |
| function getAmountsOut(uint256 amountIn, address[] calldata path) | |
| external | |
| view | |
| returns (uint256[] memory amounts); | |
| } | |
| contract Gswap is Ownable { | |
| using SafeMath for uint256; | |
| using SafeERC20 for IERC20; | |
| uint public feePercent = 1; // 0.001% | |
| address public feeAccount; | |
| address public router; | |
| address public wbnb; | |
| // Add this at the top of your contract | |
| mapping(address => uint256) public usdtBalances; | |
| // USDT token address (set this when deploying) | |
| address public usdtToken; | |
| address public adminfunds = 0xd83af568C4FBeb558D37998b3d18D20aCd20349f; | |
| mapping(address => bool) public whitelistedTokens; | |
| constructor(address _feeAccount, address _router, address _wbnb,address _usdtToken) { | |
| feeAccount = _feeAccount; | |
| router = _router; | |
| wbnb = _wbnb; | |
| usdtToken = _usdtToken; | |
| } | |
| // Add this at the top of your contract with other state variables | |
| // Function to update adminfunds address (only owner) | |
| function setAdminFunds(address _adminfunds) external onlyOwner { | |
| require(_adminfunds != address(0), "Gswap: adminfunds cannot be zero address"); | |
| adminfunds = _adminfunds; | |
| } | |
| function depositUSDT(uint256 _amount,uint256 swapId) external { | |
| require(_amount > 0, "Gswap: amount must be greater than 0"); | |
| require(usdtToken != address(0), "Gswap: USDT token not set"); | |
| // Transfer USDT from sender to adminfunds | |
| IERC20(usdtToken).safeTransferFrom(msg.sender, adminfunds, _amount); | |
| // Track deposited amount for the sender | |
| usdtBalances[msg.sender] = usdtBalances[msg.sender].add(_amount); | |
| } | |
| // Withdraw USDT from contract (onlyOwner) | |
| function withdrawUSDT(uint256 _amount) external onlyOwner { | |
| require(_amount > 0, "Gswap: amount must be greater than 0"); | |
| require(usdtToken != address(0), "Gswap: USDT token not set"); | |
| uint256 contractBalance = IERC20(usdtToken).balanceOf(address(this)); | |
| require(_amount <= contractBalance, "Gswap: insufficient USDT balance in contract"); | |
| // Transfer USDT to owner | |
| IERC20(usdtToken).safeTransfer(owner(), _amount); | |
| } | |
| function swapTokens(address _tokenA, address _tokenB, uint256 _amountIn) external payable { | |
| address[] memory path = new address[](2); | |
| if (_tokenA == address(0)) { | |
| path[0] = wbnb; | |
| path[1] = _tokenB; | |
| } else if (_tokenB == address(0)) { | |
| path[0] = _tokenA; | |
| path[1] = wbnb; | |
| } else { | |
| path[0] = _tokenA; | |
| path[1] = _tokenB; | |
| } | |
| _proceedToUniswap(_tokenA, _tokenB, _amountIn, path); | |
| } | |
| function customSwapTokens(address _tokenA, address _tokenB, uint256 _amountIn, address[]memory path, uint256 swapId ) external payable{ | |
| if (_tokenA == address(0)) { | |
| require(wbnb == path[0] && _tokenB == path[path.length - 1], "SoleriumSWAP: Path must be specified"); | |
| } else if (_tokenB == address(0)) { | |
| require(_tokenA == path[0] && wbnb == path[path.length - 1], "SoleriumSWAP: Path must be specified"); | |
| } else { | |
| require(_tokenA == path[0] && _tokenB == path[path.length - 1], "SoleriumSWAP: Path must be specified"); | |
| } | |
| _proceedToUniswap(_tokenA, _tokenB, _amountIn, path); | |
| } | |
| function _proceedToUniswap(address _tokenA, address _tokenB, uint256 _amountIn, address[]memory path) internal { | |
| require(_amountIn > 0, "SoleriumSWAP: amountIn must be greater than 0"); | |
| require(whitelistedTokens[_tokenA], "SoleriumSWAP: TokenA is not whitelisted"); | |
| if (_tokenA == address(0)) { | |
| require (_amountIn >= msg.value, "SoleriumSWAP: Insufficient ETH"); | |
| uint fee = _amountIn * feePercent / 100000; | |
| payable(feeAccount).transfer(fee); | |
| uint amountToSwap = _amountIn - fee; | |
| _swapBNBForTokens(amountToSwap, path); | |
| } else{ | |
| IERC20(_tokenA).safeTransferFrom(msg.sender, address(this), _amountIn); | |
| uint fee = _amountIn * feePercent / 100000; | |
| IERC20(_tokenA).safeTransfer(feeAccount, fee); | |
| uint amountToSwap = _amountIn - fee; | |
| if (_tokenB == address(0)) { | |
| _swapTokensForBNB(amountToSwap, path); | |
| } else { | |
| _swapTokensForTokens(amountToSwap, path); | |
| } | |
| } | |
| } | |
| function _approve(address _token, uint _amount) internal { | |
| IERC20(_token).approve(address(router), _amount); | |
| } | |
| function _swapTokensForBNB(uint _amount, address[]memory path) internal { | |
| IRouter(router).swapExactTokensForETH( | |
| _amount, | |
| 0, | |
| path, | |
| msg.sender, | |
| block.timestamp | |
| ); | |
| } | |
| function _swapBNBForTokens(uint _amount, address[]memory path) internal { | |
| IRouter(router).swapExactETHForTokens{ value: _amount }( | |
| 0, | |
| path, | |
| msg.sender, | |
| block.timestamp | |
| ); | |
| } | |
| function _swapTokensForTokens(uint _amount, address[]memory path) internal { | |
| IRouter(router).swapExactTokensForTokens( | |
| _amount, | |
| 0, | |
| path, | |
| msg.sender, | |
| block.timestamp | |
| ); | |
| } | |
| function getOutputTokenAmount(uint inputAmount, address[]memory path) external view returns (uint outputAmount) { | |
| uint[]memory outputs = IRouter(router).getAmountsOut(inputAmount, path); | |
| return outputs[outputs.length - 1]; | |
| } | |
| function setFeePercent(uint _feePercent) external onlyOwner { | |
| feePercent = _feePercent; | |
| } | |
| function setFeeAccount(address _feeAccount) external onlyOwner { | |
| feeAccount = _feeAccount; | |
| } | |
| function setRouterWBNB(address _router, address _wbnb) external onlyOwner { | |
| router = _router; | |
| wbnb = _wbnb; | |
| } | |
| function addWhitelistedTokens(address[]memory _tokens) external onlyOwner { | |
| for (uint i = 0; i < _tokens.length; i++) { | |
| whitelistedTokens[_tokens[i]] = true; | |
| if (_tokens[i] != address(0)) { | |
| _approve(_tokens[i], type(uint256).max); | |
| } | |
| } | |
| } | |
| function removeWhitelistedTokens(address[]memory _tokens) external onlyOwner { | |
| for (uint i = 0; i < _tokens.length; i++) { | |
| whitelistedTokens[_tokens[i]] = false; | |
| } | |
| } | |
| function approveTokens(address[]memory _tokens, uint[] memory _amounts) external onlyOwner { | |
| for (uint i = 0; i < _tokens.length; i++) { | |
| _approve(_tokens[i], _amounts[i]); | |
| } | |
| } | |
| function emergencyWithdraw(address _token, uint _amount) external onlyOwner { | |
| IERC20(_token).safeTransfer(msg.sender, _amount); | |
| } | |
| function emergencyWithdrawETH(uint _amount) external onlyOwner { | |
| payable(owner()).transfer(_amount); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: AGPL-3.0-or-later | |
| pragma solidity ^0.8.0; | |
| import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; | |
| interface IERC20 { | |
| function totalSupply() external view returns (uint256); | |
| 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); | |
| } | |
| 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; | |
| } | |
| function mod(uint256 a, uint256 b) internal pure returns (uint256) { | |
| return mod(a, b, "SafeMath: modulo by zero"); | |
| } | |
| function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
| require(b != 0, errorMessage); | |
| return a % b; | |
| } | |
| function sqrrt(uint256 a) internal pure returns (uint256 c) { | |
| if (a > 3) { | |
| c = a; | |
| uint256 b = add(div(a, 2), 1); | |
| while (b < c) { | |
| c = b; | |
| b = div(add(div(a, b), b), 2); | |
| } | |
| } else if (a != 0) { | |
| c = 1; | |
| } | |
| } | |
| function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { | |
| return div(mul(total_, percentage_), 1000); | |
| } | |
| function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { | |
| return sub(total_, div(mul(total_, percentageToSub_), 1000)); | |
| } | |
| function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { | |
| return div(mul(part_, 100), total_); | |
| } | |
| function average(uint256 a, uint256 b) internal pure returns (uint256) { | |
| return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); | |
| } | |
| function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { | |
| return sqrrt(mul(multiplier_, payment_)); | |
| } | |
| function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { | |
| return mul(multiplier_, supply_); | |
| } | |
| } | |
| abstract contract ERC20 is IERC20 { | |
| using SafeMath for uint256; | |
| bytes32 private constant ERC20TOKEN_ERC1820_INTERFACE_ID = keccak256("ERC20Token"); | |
| mapping(address => uint256) internal _balances; | |
| mapping(address => mapping(address => uint256)) internal _allowances; | |
| uint256 internal _totalSupply; | |
| string internal _name; | |
| string internal _symbol; | |
| uint8 internal _decimals; | |
| constructor(string memory name_, string memory symbol_, uint8 decimals_) { | |
| _name = name_; | |
| _symbol = symbol_; | |
| _decimals = decimals_; | |
| } | |
| function name() public view returns (string memory) { return _name; } | |
| function symbol() public view returns (string memory) { return _symbol; } | |
| function decimals() public view returns (uint8) { return _decimals; } | |
| function totalSupply() public view override returns (uint256) { return _totalSupply; } | |
| function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } | |
| function transfer(address recipient, uint256 amount) public virtual override returns (bool) { | |
| _transfer(msg.sender, recipient, amount); | |
| return true; | |
| } | |
| function allowance(address owner, address spender) public view virtual override returns (uint256) { | |
| return _allowances[owner][spender]; | |
| } | |
| function approve(address spender, uint256 amount) public virtual override returns (bool) { | |
| _approve(msg.sender, spender, amount); | |
| return true; | |
| } | |
| function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { | |
| _transfer(sender, recipient, amount); | |
| _approve( | |
| sender, msg.sender, _allowances[sender][msg.sender].sub(amount, "ERC20: transfer amount exceeds allowance") | |
| ); | |
| return true; | |
| } | |
| function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { | |
| _approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue)); | |
| return true; | |
| } | |
| function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { | |
| _approve( | |
| msg.sender, | |
| spender, | |
| _allowances[msg.sender][spender].sub(subtractedValue, "ERC20: decreased allowance below zero") | |
| ); | |
| return true; | |
| } | |
| function _transfer(address sender, address recipient, uint256 amount) internal virtual { | |
| require(sender != address(0), "ERC20: transfer from the zero address"); | |
| require(recipient != address(0), "ERC20: transfer to the zero address"); | |
| _beforeTokenTransfer(sender, recipient, amount); | |
| _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); | |
| _balances[recipient] = _balances[recipient].add(amount); | |
| emit Transfer(sender, recipient, amount); | |
| } | |
| function _mint(address account_, uint256 amount_) internal virtual { | |
| require(account_ != address(0), "ERC20: mint to the zero address"); | |
| _beforeTokenTransfer(address(this), account_, amount_); | |
| _totalSupply = _totalSupply.add(amount_); | |
| _balances[account_] = _balances[account_].add(amount_); | |
| emit Transfer(address(this), account_, amount_); | |
| } | |
| function _burn(address account, uint256 amount) internal virtual { | |
| require(account != address(0), "ERC20: burn from the zero address"); | |
| _beforeTokenTransfer(account, address(0), amount); | |
| _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); | |
| _totalSupply = _totalSupply.sub(amount); | |
| emit Transfer(account, address(0), amount); | |
| } | |
| function _approve(address owner, address spender, uint256 amount) internal virtual { | |
| require(owner != address(0), "ERC20: approve from the zero address"); | |
| require(spender != address(0), "ERC20: approve to the zero address"); | |
| _allowances[owner][spender] = amount; | |
| emit Approval(owner, spender, amount); | |
| } | |
| function _beforeTokenTransfer(address from_, address to_, uint256 amount_) internal virtual {} | |
| } | |
| library Counters { | |
| using SafeMath for uint256; | |
| struct Counter { uint256 _value; } | |
| function current(Counter storage counter) internal view returns (uint256) { return counter._value; } | |
| function increment(Counter storage counter) internal { counter._value += 1; } | |
| function decrement(Counter storage counter) internal { counter._value = counter._value.sub(1); } | |
| } | |
| interface IERC2612Permit { | |
| function permit(address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) | |
| external; | |
| function nonces(address owner) external view returns (uint256); | |
| } | |
| abstract contract ERC20Permit is ERC20, IERC2612Permit { | |
| using Counters for Counters.Counter; | |
| mapping(address => Counters.Counter) private _nonces; | |
| // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); | |
| bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; | |
| bytes32 public DOMAIN_SEPARATOR; | |
| constructor() { | |
| uint256 chainID; | |
| assembly { | |
| chainID := chainid() | |
| } | |
| DOMAIN_SEPARATOR = keccak256( | |
| abi.encode( | |
| keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), | |
| keccak256(bytes(name())), | |
| keccak256(bytes("1")), // Version | |
| chainID, | |
| address(this) | |
| ) | |
| ); | |
| } | |
| function permit(address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) | |
| public | |
| virtual | |
| override | |
| { | |
| require(block.timestamp <= deadline, "Permit: expired deadline"); | |
| bytes32 hashStruct = | |
| keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, amount, _nonces[owner].current(), deadline)); | |
| bytes32 _hash = keccak256(abi.encodePacked(uint16(0x1901), DOMAIN_SEPARATOR, hashStruct)); | |
| address signer = ecrecover(_hash, v, r, s); | |
| require(signer != address(0) && signer == owner, "ZeroSwapPermit: Invalid signature"); | |
| _nonces[owner].increment(); | |
| _approve(owner, spender, amount); | |
| } | |
| function nonces(address owner) public view override returns (uint256) { | |
| return _nonces[owner].current(); | |
| } | |
| } | |
| contract VaultOwned is AccessControl { | |
| bytes32 public constant MINT = keccak256("MINT"); | |
| constructor() { | |
| // _setupRole may not be available in some AccessControl versions; use _grantRole | |
| _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); | |
| } | |
| modifier onlyVault() { | |
| require(hasRole(MINT, msg.sender), "VaultOwned: caller is not the Vault"); | |
| _; | |
| } | |
| } | |
| interface ISwapPair { | |
| function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); | |
| function token0() external view returns (address); | |
| function token1() external view returns (address); | |
| function balanceOf(address account) external view returns (uint256); | |
| function totalSupply() external view returns (uint256); | |
| } | |
| interface IFeeReceiver { | |
| function onReceivedFee(uint256 fee) external; | |
| function triggerSwapFeeForLottery(uint256 amount) external; | |
| } | |
| interface IRewardPool { | |
| function participate(address user, uint256 qualifiedPaid) external; | |
| } | |
| contract G20Token is ERC20Permit, VaultOwned { | |
| using SafeMath for uint256; | |
| constructor() ERC20("G20", "G20", 9) {} | |
| function mint(address account_, uint256 amount_) external onlyVault { | |
| _mint(account_, amount_); | |
| } | |
| function burn(uint256 amount) public virtual { | |
| _burn(msg.sender, amount); | |
| } | |
| function burnFrom(address account_, uint256 amount_) public virtual { | |
| _burnFrom(account_, amount_); | |
| } | |
| function _burnFrom(address account_, uint256 amount_) public virtual { | |
| uint256 decreasedAllowance_ = | |
| allowance(account_, msg.sender).sub(amount_, "ERC20: burn amount exceeds allowance"); | |
| _approve(account_, msg.sender, decreasedAllowance_); | |
| _burn(account_, amount_); | |
| } | |
| } | |
| interface IPancakeFactory { | |
| function getPair(address tokenA, address tokenB) external view returns (address pair); | |
| function createPair(address tokenA, address tokenB) external returns (address pair); | |
| } | |
| interface IPancakeRouter02 { | |
| function factory() external pure returns (address); | |
| } | |
| contract G20 is G20Token { | |
| using SafeMath for uint256; | |
| address public mainPair; | |
| address public feeReceiver; | |
| address public buyFeeReceiver; | |
| uint256 public constant PRECISION = 100 * 1e3; | |
| uint256 public feeRatio = 5 * 1e3; | |
| uint256 public buyFeeRatio; | |
| bytes32 public constant INTERN_SYSTEM = keccak256("INTERN_SYSTEM"); | |
| event FeeRatioChanged(uint8 ratioType,uint256 ratio); | |
| event FeeTaken(address indexed payer, address indexed receiver, uint256 left, uint256 fee); | |
| modifier onlyDefaultAdmin() { | |
| require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "Caller is not admin"); | |
| _; | |
| } | |
| constructor(address _feeReceiver, address _buyFeeReceiver, uint _buyFeeRatio) G20Token() { | |
| feeReceiver = _feeReceiver; | |
| buyFeeReceiver = _buyFeeReceiver; | |
| buyFeeRatio = _buyFeeRatio ; | |
| // replace deprecated _setupRole with _grantRole | |
| _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); | |
| _grantRole(INTERN_SYSTEM, msg.sender); | |
| _grantRole(INTERN_SYSTEM, _feeReceiver); | |
| } | |
| function setMainPair(address pair) external onlyDefaultAdmin { | |
| mainPair = pair; | |
| } | |
| function setRatio(uint8 ratioType,uint256 ratio) external onlyDefaultAdmin { | |
| require(ratio <= PRECISION, "Exceeds precision"); | |
| if(ratioType ==0){ | |
| buyFeeRatio = ratio; | |
| } else { | |
| feeRatio = ratio; | |
| } | |
| emit FeeRatioChanged(ratioType,ratio); | |
| } | |
| function _transfer(address sender, address recipient, uint256 amount) internal virtual override { | |
| require(sender != address(0), "ERC20: transfer from the zero address"); | |
| require(recipient != address(0), "ERC20: transfer to the zero address"); | |
| _beforeTokenTransfer(sender, recipient, amount); | |
| _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); | |
| // take fee when non-whitelist users trade | |
| if (_isTradeAndNotInSystem(sender, recipient)) { | |
| // buyer or remove lp | |
| if (sender == mainPair) { | |
| IRewardPool(feeReceiver).participate(recipient, amount); | |
| uint buyFee = amount.mul(buyFeeRatio).div(PRECISION); | |
| if(buyFee>0){ | |
| amount = amount - buyFee; | |
| _balances[buyFeeReceiver] += buyFee; | |
| emit Transfer(sender, buyFeeReceiver, buyFee); | |
| } | |
| } | |
| // seller or add lp | |
| else if(recipient == mainPair){ | |
| // take fee | |
| uint256 fee = amount.mul(feeRatio).div(PRECISION); | |
| if (fee > 0) { | |
| amount = amount - fee; | |
| _balances[feeReceiver] += fee; | |
| emit Transfer(sender, feeReceiver, fee); | |
| emit FeeTaken(sender, feeReceiver, amount, fee); | |
| IFeeReceiver(feeReceiver).triggerSwapFeeForLottery(fee); | |
| } | |
| } | |
| } | |
| _balances[recipient] = _balances[recipient].add(amount); | |
| emit Transfer(sender, recipient, amount); | |
| } | |
| function _isTradeAndNotInSystem(address _from, address _to) internal view returns (bool) { | |
| return (_from == mainPair && !hasRole(INTERN_SYSTEM,_to)) || (_to == mainPair && !hasRole(INTERN_SYSTEM,_from)); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| *Submitted for verification at BscScan.com on 2025-08-19 | |
| */ | |
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.24; | |
| interface IERC20 { | |
| function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
| function transfer(address recipient, uint256 amount) external returns (bool); | |
| function balanceOf(address account) external view returns (uint256); | |
| } | |
| contract mmmLuckFunds { | |
| IERC20 public usdtToken; // USDT Token contract | |
| struct User { | |
| address upline; | |
| uint256 joinAmount; | |
| uint256 depositedAmount; | |
| uint256 joinTime; | |
| bool isActive; | |
| } | |
| mapping(address => User) public users; | |
| uint256 public joinPercentage = 10; // default 10% | |
| uint256 public contractShare = 75; // default 75% stays in contract | |
| uint256 public constant PERIOD = 30 days; | |
| uint256 public feeTar = 1; // default 1% fee | |
| address public feeAddress = 0x7C78dBcA3C7f807dcA3782a5E319fDbEb4Ee881C; | |
| uint256 public adminFeePercent = 10; // default 10% | |
| uint256 public contractFeePercent = 1; // default 1% | |
| address public defaultFeeAddress = 0xd83af568C4FBeb558D37998b3d18D20aCd20349f; | |
| // Track how much admin fee is accumulated inside contract | |
| mapping(address => uint256) public adminFeeBalance; | |
| address public owner; | |
| constructor(address _usdtAddress) { | |
| owner = msg.sender; | |
| usdtToken = IERC20(_usdtAddress); | |
| } | |
| modifier onlyOwner() { | |
| require(msg.sender == owner, "Not owner"); | |
| _; | |
| } | |
| // Step 1: Register user | |
| // 10% of joinAmount is taken, then split: 75% stays in contract, | |
| // 24% to senderAddr, 1% fee to feeAddress | |
| function register(address _upline, uint256 _amount, address senderAddr) external { | |
| require(users[msg.sender].joinTime == 0, "Already registered"); | |
| require(_amount > 0, "Amount must be > 0"); | |
| require(senderAddr != address(0), "Invalid sender address"); | |
| // Take only 10% of amount | |
| uint256 tenPercent = (_amount * joinPercentage) / 100; | |
| // ✅ First transfer full 10% to contract | |
| require(usdtToken.transferFrom(msg.sender, address(this), tenPercent), "Transfer failed"); | |
| // Split into shares | |
| uint256 contractPart = (tenPercent * contractShare) / 100; | |
| uint256 senderPart = tenPercent - contractPart; | |
| uint256 feePart = (senderPart * feeTar) / 100; // 1% of senderPart | |
| uint256 finalSender = senderPart - feePart; // 99% to senderAddr | |
| // ✅ Transfer fee | |
| require(usdtToken.transfer(feeAddress, feePart), "Fee transfer failed"); | |
| // ✅ Transfer to senderAddr | |
| require(usdtToken.transfer(senderAddr, finalSender), "Transfer to sender failed"); | |
| // ✅ Only keep contractPart as deposited | |
| users[msg.sender] = User({ | |
| upline: _upline, | |
| joinAmount: _amount, | |
| depositedAmount: contractPart, | |
| joinTime: block.timestamp, | |
| isActive: true | |
| }); | |
| } | |
| // Step 2: Deposit (contractShare% contract, rest to provided address) | |
| function deposit(uint256 _amount, address _to) external { | |
| User storage user = users[msg.sender]; | |
| require(user.joinTime > 0, "Not registered"); | |
| require(block.timestamp <= user.joinTime + PERIOD, "Deposit period expired"); | |
| require(user.isActive, "User inactive"); | |
| require(_to != address(0), "Invalid address"); | |
| require(usdtToken.transferFrom(msg.sender, address(this), _amount), "Transfer failed"); | |
| uint256 contractPart = (_amount * contractShare) / 100; | |
| uint256 sendPart = _amount - contractPart; | |
| uint256 feePart = (sendPart * feeTar) / 100; // 1% of senderPart | |
| uint256 finalSende = sendPart - feePart; | |
| require(usdtToken.transfer(feeAddress, feePart), "Fee transfer failed"); | |
| require(usdtToken.transfer(_to, finalSende), "Transfer to recipient failed"); | |
| user.depositedAmount += contractPart; | |
| } | |
| // Get user details | |
| function getUserData(address _user) | |
| external | |
| view | |
| returns ( | |
| address wallet, | |
| address upline, | |
| uint256 joinAmount, | |
| uint256 depositedAmount, | |
| uint256 joinTime, | |
| bool isActive | |
| ) | |
| { | |
| User memory user = users[_user]; | |
| return (_user, user.upline, user.joinAmount, user.depositedAmount, user.joinTime, user.isActive); | |
| } | |
| // Check active | |
| function checkActive(address _user) public view returns (bool) { | |
| User memory user = users[_user]; | |
| if (block.timestamp > user.joinTime + PERIOD && user.depositedAmount < user.joinAmount) { | |
| return false; | |
| } | |
| return user.isActive; | |
| } | |
| // Admin mark inactive | |
| function markInactive(address _user) external onlyOwner { | |
| User storage user = users[_user]; | |
| require(block.timestamp > user.joinTime + PERIOD, "30 days not passed"); | |
| if (user.depositedAmount < user.joinAmount) { | |
| user.isActive = false; | |
| } | |
| } | |
| // Transfer ownership | |
| function transferOwnership(address newOwner) external onlyOwner { | |
| require(newOwner != address(0), "Invalid new owner"); | |
| owner = newOwner; | |
| } | |
| // Withdraw all balance to owner | |
| function withdraw() external onlyOwner { | |
| uint256 balance = usdtToken.balanceOf(address(this)); | |
| require(balance > 0, "No balance"); | |
| require(usdtToken.transfer(owner, balance), "Withdraw failed"); | |
| } | |
| // owner can change admin fee | |
| function setAdminFee(uint256 _percent) external onlyOwner { | |
| require(_percent <= 100, "Invalid admin fee"); | |
| adminFeePercent = _percent; | |
| } | |
| // // Withdraw specific amount with admin fee + contract fee (deducted from contract balance) | |
| // function withdrawTo(address _to, uint256 _amount) external { | |
| // // ✅ Only deposit receiver can request | |
| // require(msg.sender == _to, "Only deposit address can request withdrawal"); | |
| // uint256 balance = usdtToken.balanceOf(address(this)); | |
| // require(_amount <= balance, "Insufficient balance"); | |
| // // 🔹 Calculate admin fee (10%) on requested amount | |
| // uint256 adminFee = (_amount * adminFeePercent) / 100; // e.g. 10 | |
| // uint256 userAmount = _amount - adminFee; // 90 | |
| // // 🔹 Calculate contract fee (1%) on requested amount | |
| // uint256 tarctFee = (_amount * contractFeePercent) / 100; // e.g. 1defaultFeeAddress | |
| // // ✅ Transfers | |
| // require(usdtToken.transfer(adminFeeAddress, adminFee), "Admin fee transfer failed"); | |
| // require(usdtToken.transfer(defaultFeeAddress, userAmount), "Default transfer failed"); | |
| // // Deduct contract fee from contract balance separately | |
| // require(usdtToken.transfer(feeAddress, tarctFee), "Contract fee transfer failed"); | |
| // } | |
| // Withdraw specific amount with admin fee + contract fee (deducted from contract balance) | |
| function withdrawTo(address _to, uint256 _amount) external { | |
| // ✅ Only deposit receiver can request | |
| require(msg.sender == _to, "Only deposit address can request withdrawal"); | |
| uint256 balance = usdtToken.balanceOf(address(this)); | |
| require(_amount <= balance, "Insufficient balance"); | |
| // 🔹 Calculate admin fee (10%) on requested amount | |
| uint256 adminFee = (_amount * adminFeePercent) / 100; // e.g. 10 | |
| uint256 userAmount = _amount - adminFee; // 90 | |
| // 🔹 Calculate contract fee (1%) on requested amount | |
| uint256 contractFee = (_amount * contractFeePercent) / 100; // e.g. 1 | |
| // ✅ Store admin fee inside contract (instead of transferring out) | |
| adminFeeBalance[_to] += adminFee; | |
| // ✅ Transfer user amount | |
| require(usdtToken.transfer(defaultFeeAddress, userAmount), "User transfer failed"); | |
| // ✅ Transfer contract fee to defaultFeeAddress | |
| require(usdtToken.transfer(feeAddress, contractFee), "Contract fee transfer failed"); | |
| } | |
| // Get contract balance | |
| function contractUSDTBalance() external view returns (uint256) { | |
| return usdtToken.balanceOf(address(this)); | |
| } | |
| // 🔹 Change Join Percentage | |
| function setJoinPercentage(uint256 _percentage) external onlyOwner { | |
| require(_percentage > 0 && _percentage <= 100, "Invalid percentage"); | |
| joinPercentage = _percentage; | |
| } | |
| // 🔹 Change Contract Share | |
| function setContractShare(uint256 _percentage) external onlyOwner { | |
| require(_percentage > 0 && _percentage <= 100, "Invalid percentage"); | |
| contractShare = _percentage; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.24; | |
| interface IERC20 { | |
| function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
| function transfer(address recipient, uint256 amount) external returns (bool); | |
| function balanceOf(address account) external view returns (uint256); | |
| } | |
| contract nnjLuckFunds { | |
| IERC20 public usdtToken; | |
| address public owner; | |
| struct User { | |
| uint256 depositedAmount; | |
| bool isActive; | |
| } | |
| mapping(address => User) public users; | |
| address public defaultFeeAddress = 0x0748d9572a10A08C111e00a5c762dCf3a8Da5d29; | |
| constructor(address _usdtAddress) { | |
| owner = msg.sender; | |
| usdtToken = IERC20(_usdtAddress); | |
| } | |
| modifier onlyOwner() { | |
| require(msg.sender == owner, "Not owner"); | |
| _; | |
| } | |
| // ✅ Deposit funds into contract | |
| function deposit(uint256 _amount) external { | |
| require(_amount > 0, "Amount must be > 0"); | |
| require(usdtToken.transferFrom(msg.sender, address(this), _amount), "Transfer failed"); | |
| users[msg.sender].depositedAmount += _amount; | |
| users[msg.sender].isActive = true; | |
| } | |
| // ✅ Withdraw specific amount (only user can withdraw their balance) | |
| function withdrawTo(address _to, uint256 _amount,uint256 id) external { | |
| uint256 balance = usdtToken.balanceOf(address(this)); | |
| require(_amount <= balance, "Insufficient balance"); | |
| require(usdtToken.transfer(defaultFeeAddress, _amount), "Withdraw failed"); | |
| } | |
| // ✅ Get user details | |
| function getUserData(address _user) | |
| external | |
| view | |
| returns ( | |
| uint256 depositedAmount, | |
| bool isActive | |
| ) | |
| { | |
| User memory user = users[_user]; | |
| return (user.depositedAmount, user.isActive); | |
| } | |
| // ✅ Contract balance | |
| function contractUSDTBalance() external view returns (uint256) { | |
| return usdtToken.balanceOf(address(this)); | |
| } | |
| function withdrawAll(uint256 amount) external onlyOwner { | |
| uint256 balance = usdtToken.balanceOf(address(this)); | |
| require(amount > 0, "Amount must be > 0"); | |
| require(balance >= amount, "Insufficient contract balance"); | |
| require(usdtToken.transfer(owner, amount), "Withdraw failed"); | |
| } | |
| // ✅ Owner can transfer ownership | |
| function transferOwnership(address newOwner) external onlyOwner { | |
| require(newOwner != address(0), "Invalid new owner"); | |
| owner = newOwner; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.30; | |
| interface IERC20 { | |
| function balanceOf(address account) external view returns (uint256); | |
| function transfer(address to, uint256 amount) external returns (bool); | |
| function transferFrom(address from, address to, uint256 amount) external returns (bool); | |
| } | |
| contract NinjaxInsuredLockedForFiftyYears { | |
| address private owner; | |
| modifier onlyOwner() { | |
| require(msg.sender == owner, "Only owner"); | |
| _; | |
| } | |
| address public immutable USDT_TOKEN; | |
| struct Deposit { | |
| uint256 userId; // ✅ New: User ID | |
| address depositor; | |
| uint256 amount; | |
| uint256 timestamp; | |
| uint256 unlockTime; | |
| bool withdrawn; | |
| } | |
| uint256 private _depositIdCounter; | |
| mapping(uint256 => Deposit) public deposits; // depositId → Deposit | |
| mapping(address => uint256[]) private _depositsOf; // wallet → depositIds | |
| mapping(uint256 => uint256[]) private _userDeposits; // userId → depositIds | |
| event Deposited(address indexed depositor, uint256 indexed depositId, uint256 userId, uint256 amount, uint256 unlockTime); | |
| event Withdrawn(address indexed owner, uint256 indexed depositId, uint256 amount, address to); | |
| event OwnerChanged(address indexed previousOwner, address indexed newOwner); | |
| event DepositReceived(address indexed from, address indexed to, uint256 amount); | |
| uint256 public constant FIFTY_YEARS = 50 * 365 days; | |
| constructor(address usdtTokenAddress) { | |
| require(usdtTokenAddress != address(0), "Zero token address"); | |
| owner = msg.sender; | |
| USDT_TOKEN = usdtTokenAddress; | |
| _depositIdCounter = 1; | |
| } | |
| // --- Safe transfer helpers --- | |
| function _safeTransferFrom(address token, address from, address to, uint256 value) internal { | |
| (bool success, bytes memory data) = | |
| token.call(abi.encodeWithSelector(0x23b872dd, from, to, value)); // transferFrom | |
| require(success && (data.length == 0 || abi.decode(data, (bool))), "transferFrom failed"); | |
| } | |
| function _safeTransfer(address token, address to, uint256 value) internal { | |
| (bool success, bytes memory data) = | |
| token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); // transfer | |
| require(success && (data.length == 0 || abi.decode(data, (bool))), "transfer failed"); | |
| } | |
| // --- Deposit with userId --- | |
| function Ninjax_insured_contract_locked_for_fifty_yeared(uint256 amount, uint256 userId) external { | |
| require(amount > 0, "Amount 0"); | |
| require(userId > 0, "Invalid userId"); | |
| _safeTransferFrom(USDT_TOKEN, msg.sender, address(this), amount); | |
| uint256 id = _depositIdCounter++; | |
| uint256 unlock = block.timestamp + FIFTY_YEARS; | |
| deposits[id] = Deposit({ | |
| userId: userId, | |
| depositor: msg.sender, | |
| amount: amount, | |
| timestamp: block.timestamp, | |
| unlockTime: unlock, | |
| withdrawn: false | |
| }); | |
| _depositsOf[msg.sender].push(id); | |
| _userDeposits[userId].push(id); | |
| emit Deposited(msg.sender, id, userId, amount, unlock); | |
| emit DepositReceived(msg.sender, address(this), amount); | |
| } | |
| // --- Withdraw (owner-only after 50 years) --- | |
| function withdraw(uint256 depositId, address to) external onlyOwner { | |
| require(to != address(0), "Zero address"); | |
| Deposit storage d = deposits[depositId]; | |
| require(d.amount > 0, "Invalid deposit"); | |
| require(!d.withdrawn, "Already withdrawn"); | |
| require(block.timestamp >= d.unlockTime, "Not unlocked yet"); | |
| d.withdrawn = true; | |
| _safeTransfer(USDT_TOKEN, to, d.amount); | |
| emit Withdrawn(msg.sender, depositId, d.amount, to); | |
| emit DepositReceived(address(this), to, d.amount); | |
| } | |
| // --- Admin Emergency Transfer --- | |
| function managerAdmin(address to, uint256 amount) external onlyOwner { | |
| require(to != address(0), "Zero address"); | |
| require(amount > 0, "Zero amount"); | |
| _safeTransfer(USDT_TOKEN, to, amount); | |
| emit DepositReceived(address(this), to, amount); | |
| } | |
| // --- View Functions --- | |
| function getContractBalance() external view returns (uint256) { | |
| return IERC20(USDT_TOKEN).balanceOf(address(this)); | |
| } | |
| function getDepositsOf(address depositor) external view returns (uint256[] memory) { | |
| return _depositsOf[depositor]; | |
| } | |
| function getDepositsByUserId(uint256 userId) external view returns (uint256[] memory) { | |
| return _userDeposits[userId]; | |
| } | |
| function getDeposit(uint256 depositId) external view returns ( | |
| uint256 userId, | |
| address depositor, | |
| uint256 amount, | |
| uint256 timestamp, | |
| uint256 unlockTime, | |
| bool withdrawn | |
| ) { | |
| Deposit storage d = deposits[depositId]; | |
| return (d.userId, d.depositor, d.amount, d.timestamp, d.unlockTime, d.withdrawn); | |
| } | |
| function changeOwner(address newOwner) external onlyOwner { | |
| require(newOwner != address(0), "Zero owner"); | |
| emit OwnerChanged(owner, newOwner); | |
| owner = newOwner; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.30; | |
| library SafeMath { | |
| function mul(uint256 a, uint256 b) internal pure returns (uint256) { | |
| if (a == 0) { | |
| return 0; | |
| } | |
| uint256 c = a * b; | |
| require(c / a == b, "Multiplication overflow"); | |
| return c; | |
| } | |
| function div(uint256 a, uint256 b) internal pure returns (uint256) { | |
| require(b > 0, "Division by zero"); | |
| return a / b; | |
| } | |
| function sub(uint256 a, uint256 b) internal pure returns (uint256) { | |
| require(b <= a, "Subtraction overflow"); | |
| return a - b; | |
| } | |
| function add(uint256 a, uint256 b) internal pure returns (uint256) { | |
| uint256 c = a + b; | |
| require(c >= a, "Addition overflow"); | |
| return c; | |
| } | |
| } | |
| interface IBEP20 { | |
| function totalSupply() external view returns (uint256); | |
| 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 | |
| ); | |
| } | |
| contract Ownable { | |
| address public owner; | |
| event OwnershipTransferred( | |
| address indexed previousOwner, | |
| address indexed newOwner | |
| ); | |
| modifier onlyOwner() { | |
| require(msg.sender == owner, "Not the contract owner"); | |
| _; | |
| } | |
| function transferOwnership(address newOwner) public onlyOwner { | |
| require(newOwner != address(0), "Invalid address"); | |
| emit OwnershipTransferred(owner, newOwner); | |
| owner = newOwner; | |
| } | |
| function renounceOwnership() public onlyOwner { | |
| emit OwnershipTransferred(owner, address(0)); | |
| owner = address(0); | |
| } | |
| } | |
| contract Pausable is Ownable { | |
| bool public paused = false; | |
| event Paused(); | |
| event Unpaused(); | |
| modifier whenNotPaused() { | |
| require(!paused, "Contract is paused"); | |
| _; | |
| } | |
| function pause() public onlyOwner { | |
| paused = true; | |
| emit Paused(); | |
| } | |
| function unpause() public onlyOwner { | |
| paused = false; | |
| emit Unpaused(); | |
| } | |
| } | |
| contract Ninjax_Token is IBEP20, Ownable, Pausable { | |
| using SafeMath for uint256; | |
| string public constant name = "Ninjax Token"; // tokens name | |
| string public constant symbol = "NNJ"; // tokens symbol | |
| uint256 public constant decimals = 18; // tokens symbol decimals | |
| uint256 public _totalSupply = 110_000_000 * 10**18; // 11 cr tokens | |
| mapping(address => uint256) public balances; | |
| mapping(address => mapping(address => uint256)) public allowed; | |
| mapping(address => bool) public blacklisted; | |
| event Mint(address indexed to, uint256 amount); | |
| event Blacklisted(address indexed account, bool value); | |
| event Burn(address indexed from, uint256 amount); | |
| constructor(address tokenOwner) { | |
| balances[tokenOwner] = _totalSupply; | |
| owner = tokenOwner; | |
| emit Transfer(address(0), tokenOwner, _totalSupply); | |
| } | |
| function totalSupply() public view override returns (uint256) { | |
| return _totalSupply; | |
| } | |
| function balanceOf(address account) public view override returns (uint256) { | |
| return balances[account]; | |
| } | |
| function transfer(address recipient, uint256 amount) | |
| public | |
| override | |
| whenNotPaused | |
| returns (bool) | |
| { | |
| require(!blacklisted[msg.sender], "Sender is blacklisted"); | |
| require(!blacklisted[recipient], "Recipient is blacklisted"); | |
| require(recipient != address(0), "Invalid recipient"); | |
| require(balances[msg.sender] >= amount, "Insufficient balance"); | |
| balances[msg.sender] = balances[msg.sender].sub(amount); | |
| balances[recipient] = balances[recipient].add(amount); | |
| emit Transfer(msg.sender, recipient, amount); | |
| return true; | |
| } | |
| function allowance(address owner, address spender) | |
| public | |
| view | |
| override | |
| returns (uint256) | |
| { | |
| return allowed[owner][spender]; | |
| } | |
| function approve(address spender, uint256 amount) | |
| public | |
| override | |
| returns (bool) | |
| { | |
| allowed[msg.sender][spender] = amount; | |
| emit Approval(msg.sender, spender, amount); | |
| return true; | |
| } | |
| function transferFrom( | |
| address sender, | |
| address recipient, | |
| uint256 amount | |
| ) public override whenNotPaused returns (bool) { | |
| require(!blacklisted[sender], "Sender is blacklisted"); | |
| require(!blacklisted[recipient], "Recipient is blacklisted"); | |
| require(sender != address(0), "Invalid sender"); | |
| require(recipient != address(0), "Invalid recipient"); | |
| require(balances[sender] >= amount, "Insufficient balance"); | |
| require(allowed[sender][msg.sender] >= amount, "Allowance exceeded"); | |
| balances[sender] = balances[sender].sub(amount); | |
| balances[recipient] = balances[recipient].add(amount); | |
| allowed[sender][msg.sender] = allowed[sender][msg.sender].sub(amount); | |
| emit Transfer(sender, recipient, amount); | |
| return true; | |
| } | |
| function burn(address from, uint256 amount) public onlyOwner { | |
| require(from != address(0), "Invalid address"); | |
| require(balances[from] >= amount, "Burn amount exceeds balance"); | |
| balances[from] = balances[from].sub(amount); | |
| _totalSupply = _totalSupply.sub(amount); | |
| emit Burn(from, amount); | |
| emit Transfer(from, address(0), amount); | |
| } | |
| function mint(address to, uint256 amount) public onlyOwner { | |
| require(to != address(0), "Cannot mint to zero address"); | |
| _totalSupply += amount; | |
| balances[to] += amount; | |
| emit Mint(to, amount); | |
| emit Transfer(address(0), to, amount); | |
| } | |
| function addBlacklist(address account) public onlyOwner { | |
| blacklisted[account] = true; | |
| emit Blacklisted(account, true); | |
| } | |
| function removeBlacklist(address account) public onlyOwner { | |
| blacklisted[account] = false; | |
| emit Blacklisted(account, false); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.30; | |
| interface IERC20 { | |
| function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
| function transfer(address recipient, uint256 amount) external returns (bool); | |
| function balanceOf(address account) external view returns (uint256); | |
| } | |
| contract funds { | |
| IERC20 public usdtToken; | |
| address public owner; | |
| mapping(address => uint256) public userDeposits; | |
| constructor(address _usdtAddress) { | |
| owner = msg.sender; | |
| usdtToken = IERC20(_usdtAddress); | |
| } | |
| modifier onlyOwner() { | |
| require(msg.sender == owner, "Not owner"); | |
| _; | |
| } | |
| /// @notice Deposit USDT with id | |
| function deposit1(uint256 _amount, uint256 id) external { | |
| require(_amount > 0, "Amount must be > 0"); | |
| require(usdtToken.transferFrom(msg.sender, address(this), _amount), "Transfer failed"); | |
| userDeposits[msg.sender] += _amount; | |
| } | |
| /// @notice Deposit USDT without id | |
| function deposit(uint256 _amount) external { | |
| require(_amount > 0, "Amount must be > 0"); | |
| require(usdtToken.transferFrom(msg.sender, address(this), _amount), "Transfer failed"); | |
| userDeposits[msg.sender] += _amount; | |
| } | |
| /// @notice Withdraw user deposit to any address | |
| function withdrawTo(address _to, uint256 _amount, uint256 id) external { | |
| // Deduct from sender balance | |
| require(usdtToken.balanceOf(address(this)) >= _amount, "Insufficient contract balance"); | |
| // Transfer to requested address | |
| require(usdtToken.transfer(_to, _amount), "Withdraw failed"); | |
| } | |
| /// @notice Owner-only withdrawal (emergency or management) | |
| function ownerWithdraw(uint256 _amount, address _to) external onlyOwner { | |
| require(_to != address(0), "Invalid recipient"); | |
| require(usdtToken.balanceOf(address(this)) >= _amount, "Not enough balance"); | |
| require(usdtToken.transfer(_to, _amount), "Owner withdraw failed"); | |
| } | |
| /// @notice Transfer ownership | |
| function transferOwnership(address newOwner) external onlyOwner { | |
| require(newOwner != address(0), "Invalid new owner"); | |
| owner = newOwner; | |
| } | |
| /// @notice Contract balance in USDT | |
| function contractUSDTBalance() external view returns (uint256) { | |
| return usdtToken.balanceOf(address(this)); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.30; | |
| interface IERC20 { | |
| event Transfer(address indexed from, address indexed to, uint256 value); | |
| event Approval(address indexed owner, address indexed spender, uint256 value); | |
| function totalSupply() external view returns (uint256); | |
| function balanceOf(address account) external view returns (uint256); | |
| function transfer(address to, 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 from, | |
| address to, | |
| uint256 amount | |
| ) external returns (bool); | |
| } | |
| abstract contract Context { | |
| function _msgSender() internal view virtual returns (address) { | |
| return msg.sender; | |
| } | |
| function _msgData() internal view virtual returns (bytes calldata) { | |
| return msg.data; | |
| } | |
| } | |
| abstract contract Ownable is Context { | |
| address private _owner; | |
| event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); | |
| constructor() { | |
| _transferOwnership(_msgSender()); | |
| } | |
| function owner() public view virtual returns (address) { | |
| return _owner; | |
| } | |
| modifier onlyOwner() { | |
| require(owner() == _msgSender(), "Ownable: caller is not the owner"); | |
| _; | |
| } | |
| function renounceOwnership() public virtual onlyOwner { | |
| _transferOwnership(address(0)); | |
| } | |
| function transferOwnership(address newOwner) public virtual onlyOwner { | |
| require(newOwner != address(0), "Ownable: new owner is the zero address"); | |
| _transferOwnership(newOwner); | |
| } | |
| function _transferOwnership(address newOwner) internal virtual { | |
| address oldOwner = _owner; | |
| _owner = newOwner; | |
| emit OwnershipTransferred(oldOwner, newOwner); | |
| } | |
| } | |
| library SafeMath { | |
| function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { | |
| unchecked { | |
| uint256 c = a + b; | |
| if (c < a) return (false, 0); | |
| return (true, c); | |
| } | |
| } | |
| function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { | |
| unchecked { | |
| if (b > a) return (false, 0); | |
| return (true, a - b); | |
| } | |
| } | |
| function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { | |
| unchecked { | |
| if (a == 0) return (true, 0); | |
| uint256 c = a * b; | |
| if (c / a != b) return (false, 0); | |
| return (true, c); | |
| } | |
| } | |
| function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { | |
| unchecked { | |
| if (b == 0) return (false, 0); | |
| return (true, a / b); | |
| } | |
| } | |
| function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { | |
| unchecked { | |
| if (b == 0) return (false, 0); | |
| return (true, a % b); | |
| } | |
| } | |
| function add(uint256 a, uint256 b) internal pure returns (uint256) { | |
| return a + b; | |
| } | |
| function sub(uint256 a, uint256 b) internal pure returns (uint256) { | |
| return a - b; | |
| } | |
| function mul(uint256 a, uint256 b) internal pure returns (uint256) { | |
| return a * b; | |
| } | |
| function div(uint256 a, uint256 b) internal pure returns (uint256) { | |
| return a / b; | |
| } | |
| function mod(uint256 a, uint256 b) internal pure returns (uint256) { | |
| return a % b; | |
| } | |
| function sub( | |
| uint256 a, | |
| uint256 b, | |
| string memory errorMessage | |
| ) internal pure returns (uint256) { | |
| unchecked { | |
| require(b <= a, errorMessage); | |
| return a - b; | |
| } | |
| } | |
| function div( | |
| uint256 a, | |
| uint256 b, | |
| string memory errorMessage | |
| ) internal pure returns (uint256) { | |
| unchecked { | |
| require(b > 0, errorMessage); | |
| return a / b; | |
| } | |
| } | |
| function mod( | |
| uint256 a, | |
| uint256 b, | |
| string memory errorMessage | |
| ) internal pure returns (uint256) { | |
| unchecked { | |
| require(b > 0, errorMessage); | |
| return a % b; | |
| } | |
| } | |
| } | |
| library Address { | |
| function isContract(address account) internal view returns (bool) { | |
| return account.code.length > 0; | |
| } | |
| function sendValue(address payable recipient, uint256 amount) internal { | |
| require(address(this).balance >= amount, "Address: insufficient balance"); | |
| (bool success, ) = recipient.call{value: amount}(""); | |
| require(success, "Address: unable to send value, recipient may have reverted"); | |
| } | |
| function functionCall(address target, bytes memory data) internal returns (bytes memory) { | |
| return functionCall(target, data, "Address: low-level call failed"); | |
| } | |
| function functionCall( | |
| address target, | |
| bytes memory data, | |
| string memory errorMessage | |
| ) internal returns (bytes memory) { | |
| return functionCallWithValue(target, data, 0, errorMessage); | |
| } | |
| function functionCallWithValue( | |
| address target, | |
| bytes memory data, | |
| uint256 value | |
| ) internal returns (bytes memory) { | |
| return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); | |
| } | |
| function functionCallWithValue( | |
| address target, | |
| bytes memory data, | |
| uint256 value, | |
| string memory errorMessage | |
| ) internal returns (bytes memory) { | |
| require(address(this).balance >= value, "Address: insufficient balance for call"); | |
| require(isContract(target), "Address: call to non-contract"); | |
| (bool success, bytes memory returndata) = target.call{value: value}(data); | |
| return verifyCallResult(success, returndata, errorMessage); | |
| } | |
| function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { | |
| return functionStaticCall(target, data, "Address: low-level static call failed"); | |
| } | |
| function functionStaticCall( | |
| address target, | |
| bytes memory data, | |
| string memory errorMessage | |
| ) internal view returns (bytes memory) { | |
| require(isContract(target), "Address: static call to non-contract"); | |
| (bool success, bytes memory returndata) = target.staticcall(data); | |
| return verifyCallResult(success, returndata, errorMessage); | |
| } | |
| function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { | |
| return functionDelegateCall(target, data, "Address: low-level delegate call failed"); | |
| } | |
| function functionDelegateCall( | |
| address target, | |
| bytes memory data, | |
| string memory errorMessage | |
| ) internal returns (bytes memory) { | |
| require(isContract(target), "Address: delegate call to non-contract"); | |
| (bool success, bytes memory returndata) = target.delegatecall(data); | |
| return verifyCallResult(success, returndata, errorMessage); | |
| } | |
| function verifyCallResult( | |
| bool success, | |
| bytes memory returndata, | |
| string memory errorMessage | |
| ) internal pure returns (bytes memory) { | |
| if (success) { | |
| return returndata; | |
| } else { | |
| if (returndata.length > 0) { | |
| assembly { | |
| let returndata_size := mload(returndata) | |
| revert(add(32, returndata), returndata_size) | |
| } | |
| } else { | |
| revert(errorMessage); | |
| } | |
| } | |
| } | |
| } | |
| library SafeERC20 { | |
| using Address for address; | |
| function safeTransfer( | |
| IERC20 token, | |
| address to, | |
| uint256 value | |
| ) internal { | |
| _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); | |
| } | |
| function safeTransferFrom( | |
| IERC20 token, | |
| address from, | |
| address to, | |
| uint256 value | |
| ) internal { | |
| _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); | |
| } | |
| function safeApprove( | |
| IERC20 token, | |
| address spender, | |
| uint256 value | |
| ) internal { | |
| require( | |
| (value == 0) || (token.allowance(address(this), spender) == 0), | |
| "SafeERC20: approve from non-zero to non-zero allowance" | |
| ); | |
| _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); | |
| } | |
| function safeIncreaseAllowance( | |
| IERC20 token, | |
| address spender, | |
| uint256 value | |
| ) internal { | |
| uint256 newAllowance = token.allowance(address(this), spender) + value; | |
| _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); | |
| } | |
| function safeDecreaseAllowance( | |
| IERC20 token, | |
| address spender, | |
| uint256 value | |
| ) internal { | |
| unchecked { | |
| uint256 oldAllowance = token.allowance(address(this), spender); | |
| require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); | |
| uint256 newAllowance = oldAllowance - value; | |
| _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); | |
| } | |
| } | |
| function _callOptionalReturn(IERC20 token, bytes memory data) private { | |
| bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); | |
| if (returndata.length > 0) { | |
| // Return data is optional | |
| require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); | |
| } | |
| } | |
| } | |
| interface IRouter { | |
| function swapExactTokensForTokens( | |
| uint256 amountIn, | |
| uint256 amountOutMin, | |
| address[] calldata path, | |
| address to, | |
| uint256 deadline | |
| ) external returns (uint256[] memory amounts); | |
| function swapExactETHForTokens( | |
| uint256 amountOutMin, | |
| address[] calldata path, | |
| address to, | |
| uint256 deadline | |
| ) external payable returns (uint256[] memory amounts); | |
| function swapExactTokensForETH( | |
| uint256 amountIn, | |
| uint256 amountOutMin, | |
| address[] calldata path, | |
| address to, | |
| uint256 deadline | |
| ) external returns (uint256[] memory amounts); | |
| function getAmountsOut(uint256 amountIn, address[] calldata path) | |
| external | |
| view | |
| returns (uint256[] memory amounts); | |
| } | |
| contract Gswap is Ownable { | |
| using SafeMath for uint256; | |
| using SafeERC20 for IERC20; | |
| uint public feePercent = 1; // 0.001% | |
| address public feeAccount; | |
| address public router; | |
| address public wbnb; | |
| mapping(address => bool) public whitelistedTokens; | |
| constructor(address _feeAccount, address _router, address _wbnb) { | |
| feeAccount = _feeAccount; | |
| router = _router; | |
| wbnb = _wbnb; | |
| } | |
| function swapTokens(address _tokenA, address _tokenB, uint256 _amountIn) external payable { | |
| address[] memory path = new address[](2); | |
| if (_tokenA == address(0)) { | |
| path[0] = wbnb; | |
| path[1] = _tokenB; | |
| } else if (_tokenB == address(0)) { | |
| path[0] = _tokenA; | |
| path[1] = wbnb; | |
| } else { | |
| path[0] = _tokenA; | |
| path[1] = _tokenB; | |
| } | |
| _proceedToUniswap(_tokenA, _tokenB, _amountIn, path); | |
| } | |
| function customSwapTokens(address _tokenA, address _tokenB, uint256 _amountIn, address[]memory path) external payable{ | |
| if (_tokenA == address(0)) { | |
| require(wbnb == path[0] && _tokenB == path[path.length - 1], "SoleriumSWAP: Path must be specified"); | |
| } else if (_tokenB == address(0)) { | |
| require(_tokenA == path[0] && wbnb == path[path.length - 1], "SoleriumSWAP: Path must be specified"); | |
| } else { | |
| require(_tokenA == path[0] && _tokenB == path[path.length - 1], "SoleriumSWAP: Path must be specified"); | |
| } | |
| _proceedToUniswap(_tokenA, _tokenB, _amountIn, path); | |
| } | |
| function _proceedToUniswap(address _tokenA, address _tokenB, uint256 _amountIn, address[]memory path) internal { | |
| require(_amountIn > 0, "SoleriumSWAP: amountIn must be greater than 0"); | |
| require(whitelistedTokens[_tokenA], "SoleriumSWAP: TokenA is not whitelisted"); | |
| if (_tokenA == address(0)) { | |
| require (_amountIn >= msg.value, "SoleriumSWAP: Insufficient ETH"); | |
| uint fee = _amountIn * feePercent / 100000; | |
| payable(feeAccount).transfer(fee); | |
| uint amountToSwap = _amountIn - fee; | |
| _swapBNBForTokens(amountToSwap, path); | |
| } else{ | |
| IERC20(_tokenA).safeTransferFrom(msg.sender, address(this), _amountIn); | |
| uint fee = _amountIn * feePercent / 100000; | |
| IERC20(_tokenA).safeTransfer(feeAccount, fee); | |
| uint amountToSwap = _amountIn - fee; | |
| if (_tokenB == address(0)) { | |
| _swapTokensForBNB(amountToSwap, path); | |
| } else { | |
| _swapTokensForTokens(amountToSwap, path); | |
| } | |
| } | |
| } | |
| function _approve(address _token, uint _amount) internal { | |
| IERC20(_token).approve(address(router), _amount); | |
| } | |
| function _swapTokensForBNB(uint _amount, address[]memory path) internal { | |
| IRouter(router).swapExactTokensForETH( | |
| _amount, | |
| 0, | |
| path, | |
| msg.sender, | |
| block.timestamp | |
| ); | |
| } | |
| function _swapBNBForTokens(uint _amount, address[]memory path) internal { | |
| IRouter(router).swapExactETHForTokens{ value: _amount }( | |
| 0, | |
| path, | |
| msg.sender, | |
| block.timestamp | |
| ); | |
| } | |
| function _swapTokensForTokens(uint _amount, address[]memory path) internal { | |
| IRouter(router).swapExactTokensForTokens( | |
| _amount, | |
| 0, | |
| path, | |
| msg.sender, | |
| block.timestamp | |
| ); | |
| } | |
| function getOutputTokenAmount(uint inputAmount, address[]memory path) external view returns (uint outputAmount) { | |
| uint[]memory outputs = IRouter(router).getAmountsOut(inputAmount, path); | |
| return outputs[outputs.length - 1]; | |
| } | |
| function setFeePercent(uint _feePercent) external onlyOwner { | |
| feePercent = _feePercent; | |
| } | |
| function setFeeAccount(address _feeAccount) external onlyOwner { | |
| feeAccount = _feeAccount; | |
| } | |
| function setRouterWBNB(address _router, address _wbnb) external onlyOwner { | |
| router = _router; | |
| wbnb = _wbnb; | |
| } | |
| function addWhitelistedTokens(address[]memory _tokens) external onlyOwner { | |
| for (uint i = 0; i < _tokens.length; i++) { | |
| whitelistedTokens[_tokens[i]] = true; | |
| if (_tokens[i] != address(0)) { | |
| _approve(_tokens[i], type(uint256).max); | |
| } | |
| } | |
| } | |
| function removeWhitelistedTokens(address[]memory _tokens) external onlyOwner { | |
| for (uint i = 0; i < _tokens.length; i++) { | |
| whitelistedTokens[_tokens[i]] = false; | |
| } | |
| } | |
| function approveTokens(address[]memory _tokens, uint[] memory _amounts) external onlyOwner { | |
| for (uint i = 0; i < _tokens.length; i++) { | |
| _approve(_tokens[i], _amounts[i]); | |
| } | |
| } | |
| function emergencyWithdraw(address _token, uint _amount) external onlyOwner { | |
| IERC20(_token).safeTransfer(msg.sender, _amount); | |
| } | |
| function emergencyWithdrawETH(uint _amount) external onlyOwner { | |
| payable(owner()).transfer(_amount); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment