파일 1 / 1 : Token.sol
pragma solidity ^0.8.19;
interface Callable {
function tokenCallback(address _from, uint256 _tokens, bytes calldata _data) external returns (bool);
}
interface Router {
function WETH() external pure returns (address);
function factory() external pure returns (address);
function addLiquidityETH(address, uint256, uint256, uint256, address, uint256) external payable returns (uint256, uint256, uint256);
function swapExactETHForTokens(uint256, address[] calldata, address, uint256) external payable returns (uint256[] memory);
}
interface Factory {
function createPair(address, address) external returns (address);
}
interface Pair {
function balanceOf(address) external view returns (uint256);
function transfer(address, uint256) external returns (bool);
}
contract Token {
uint256 constant private UINT_MAX = type(uint256).max;
uint256 constant private MAX_NAME_LENGTH = 32;
uint256 constant private MIN_SUPPLY = 1e16;
uint256 constant private MAX_SUPPLY = 1e33;
uint256 constant private PERCENT_PRECISION = 1000;
Router constant private ROUTER = Router(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
string public name;
string public symbol;
uint8 constant public decimals = 18;
string constant public source = "Created with Bossman's Bakery (bakery.mullet.capital)!";
struct User {
uint256 balance;
mapping(address => uint256) allowance;
}
struct Info {
bool locked;
address pair;
address creator;
uint256 totalSupply;
uint256 initialMarketCap;
uint256 transferTax;
uint256 creatorFee;
mapping(address => User) users;
}
Info private info;
event Transfer(address indexed from, address indexed to, uint256 tokens);
event Approval(address indexed owner, address indexed spender, uint256 tokens);
function lock() external {
require(!info.locked);
require(totalSupply() == 0);
info.locked = true;
}
function initialize(address _creator, string memory _name, string memory _symbol, uint256 _totalSupply, uint256 _initialMarketCap, uint256 _transferTax, uint256 _creatorFee) external payable {
require(!info.locked);
require(totalSupply() == 0);
require(bytes(_name).length > 0 && bytes(_name).length <= MAX_NAME_LENGTH);
require(bytes(_symbol).length > 0 && bytes(_symbol).length <= MAX_NAME_LENGTH);
require(_totalSupply >= MIN_SUPPLY && _totalSupply <= MAX_SUPPLY);
require(_initialMarketCap > 0);
require(_transferTax < PERCENT_PRECISION);
require(_creatorFee < PERCENT_PRECISION);
require(msg.value >= _initialMarketCap);
info.creator = _creator;
name = _name;
symbol = _symbol;
info.totalSupply = _totalSupply;
info.users[address(this)].balance = _totalSupply;
emit Transfer(address(0x0), address(this), _totalSupply);
info.initialMarketCap = _initialMarketCap;
info.creatorFee = _creatorFee;
_createLP();
info.transferTax = _transferTax;
}
function collectTax() external {
address _this = address(this);
uint256 _tokens = balanceOf(_this);
require(_tokens > 0);
_transfer(_this, creator(), _tokens / 2);
_transfer(_this, 0xe6c791FBd46dB3f4EdA5f7Bb76474F4FA530733E, _tokens / 3);
_transfer(_this, 0xc28C9da0F8a500DFfC16Ff09a3DD1Cc4c530D346, _tokens / 6);
}
function transfer(address _to, uint256 _tokens) external returns (bool) {
return _transfer(msg.sender, _to, _tokens);
}
function approve(address _spender, uint256 _tokens) external returns (bool) {
return _approve(msg.sender, _spender, _tokens);
}
function transferFrom(address _from, address _to, uint256 _tokens) external returns (bool) {
unchecked {
uint256 _allowance = allowance(_from, msg.sender);
require(_allowance >= _tokens);
if (_allowance != UINT_MAX) {
info.users[_from].allowance[msg.sender] -= _tokens;
}
return _transfer(_from, _to, _tokens);
}
}
function transferAndCall(address _to, uint256 _tokens, bytes calldata _data) external returns (bool) {
_transfer(msg.sender, _to, _tokens);
uint32 _size;
assembly {
_size := extcodesize(_to)
}
if (_size > 0) {
require(Callable(_to).tokenCallback(msg.sender, _tokens, _data));
}
return true;
}
function creator() public view returns (address) {
return info.creator;
}
function pair() public view returns (address) {
return info.pair;
}
function totalSupply() public view returns (uint256) {
return info.totalSupply;
}
function balanceOf(address _user) public view returns (uint256) {
return info.users[_user].balance;
}
function allowance(address _user, address _spender) public view returns (uint256) {
return info.users[_user].allowance[_spender];
}
function initialMarketCap() external view returns (string memory) {
return string(abi.encodePacked(_uint2str(info.initialMarketCap, 18, 5), " ETH"));
}
function transferTax() external view returns (string memory) {
return string(abi.encodePacked(_uint2str(info.transferTax * 100, 3, 3), "%"));
}
function creatorFee() external view returns (string memory) {
return string(abi.encodePacked(_uint2str(info.creatorFee * 100, 3, 3), "%"));
}
function _createLP() internal {
address _this = address(this);
address _weth = ROUTER.WETH();
_approve(_this, address(ROUTER), totalSupply());
info.pair = Factory(ROUTER.factory()).createPair(_weth, _this);
( , , uint256 _lpTokens) = ROUTER.addLiquidityETH{ value: info.initialMarketCap }(_this, totalSupply(), 0, 0, _this, block.timestamp);
Pair _pair = Pair(pair());
if (info.creatorFee > 0) {
_pair.transfer(creator(), _lpTokens * info.creatorFee / PERCENT_PRECISION);
}
_pair.transfer(address(0x0), _pair.balanceOf(_this));
if (msg.value > info.initialMarketCap) {
address[] memory _path = new address[](2);
_path[0] = _weth;
_path[1] = _this;
ROUTER.swapExactETHForTokens{ value: msg.value - info.initialMarketCap }(0, _path, creator(), block.timestamp);
}
}
function _approve(address _owner, address _spender, uint256 _tokens) internal returns (bool) {
info.users[_owner].allowance[_spender] = _tokens;
emit Approval(_owner, _spender, _tokens);
return true;
}
function _transfer(address _from, address _to, uint256 _tokens) internal returns (bool) {
unchecked {
require(_tokens > 0);
require(balanceOf(_from) >= _tokens);
address _this = address(this);
if (info.transferTax == 0 || _from == _this || _to == _this || _from == creator()) {
info.users[_from].balance -= _tokens;
info.users[_to].balance += _tokens;
emit Transfer(_from, _to, _tokens);
} else {
info.users[_from].balance -= _tokens;
uint256 _tax = _tokens * info.transferTax / PERCENT_PRECISION;
info.users[_this].balance += _tax;
emit Transfer(_from, _this, _tax);
info.users[_to].balance += _tokens - _tax;
emit Transfer(_from, _to, _tokens - _tax);
}
return true;
}
}
function _uint2str(uint256 _value, uint256 _scale, uint256 _maxDecimals) internal pure returns (string memory str) {
uint256 _d = _scale > _maxDecimals ? _maxDecimals : _scale;
uint256 _n = _value / 10**(_scale > _d ? _scale - _d : 0);
if (_n == 0) {
return "0";
}
uint256 _digits = 1;
uint256 _tmp = _n;
while (_tmp > 9) {
_tmp /= 10;
_digits++;
}
_tmp = _digits > _d ? _digits : _d + 1;
uint256 _offset = (_tmp > _d + 1 ? _tmp - _d - 1 > _d ? _d : _tmp - _d - 1 : 0);
for (uint256 i = 0; i < _tmp - _offset; i++) {
uint256 _dec = i < _tmp - _digits ? 0 : (_n / (10**(_tmp - i - 1))) % 10;
bytes memory _char = new bytes(1);
_char[0] = bytes1(uint8(_dec) + 48);
str = string(abi.encodePacked(str, string(_char)));
if (i < _tmp - _d - 1) {
if ((i + 1) % 3 == (_tmp - _d) % 3) {
str = string(abi.encodePacked(str, ","));
}
} else {
if ((_n / 10**_offset) % 10**(_tmp - _offset - i - 1) == 0) {
break;
} else if (i == _tmp - _d - 1) {
str = string(abi.encodePacked(str, "."));
}
}
}
}
}