账户
0x26...f0e6
UBOMB

UBOMB

US$0.00
此合同的源代码已经过验证!
合同元数据
编译器
0.5.17+commit.d19bba13
语言
Solidity
合同源代码
文件 1 的 1:UniBombV3.sol
//                          _
//                        /   \
//                       .     \
//                      /       \
//                 .BBBBB;     . | .
//               BBBBBBBBB      \|/
//              ;BBIBBBBb     `--+--'
//        .=YRBBBBBBBBBBB       /|\
//      =RBBBBBBBBBBBBBB;      . . .
//    ;BBBR=VBBBBBBBBBBBV.
//   tBBR::VBBBBBBBBBBBBBB:      _   _        ______                 _
//  tBBt ;BBBBBBBBBBBBBBBBB.    | | | |       | ___ \               | |
// ;BBY ;BBBBBBBBBBBBBBBBBBV    | | | |_ __  ♥| |_/ / ___  _ __ ___ | |_
// XBB .BBBBBBBBBBBBBBBBBBBB:   | | | |  _ \| | ___ \/ _ \|  _   _ \|  _ \
// BBI +BBBBBBBBBBBBBBBBBBBBi   | |_| | | | | | |_/ / (_) | | | | | | |_) |
//.BB= XBBBBBBBBBBBBBBBBBBBBY    \___/|_| |_|_\____/ \___/|_| |_| |_|____/
// BBt YBBBBBBBBBBBBBBBBBBBBi
// VBB +BBBBBBBBBBBBBBBBBBBB:
// ;BB+ BBBBBBBBBBBBBBBBBBBR     ██╗   ██╗██████╗   Created by Dorf and Mr Fahrenheit
//  tBBVBBBBBBBBBBBBBBBBBBB.     ██║   ██║╚════██╗
//   tBBBBBBBBBBBBBBBBBBBB:      ██║   ██║ █████╔╝    https://unibomb.it/ - created by Karl
//    ;BBBBBBBBBBBBBBBBBY        ╚██╗ ██╔╝ ╚═══██╗    https://t.me/UniBomb
//      +BBBBBBBBBBBBBY:          ╚████╔╝ ██████╔╝    https://discord.gg/Jmsbnsx
//        :+YRBBBRVt;
//
//-------------------------------------------------------------------------
//
//Contributions:
//~~~~~~~~~~ MrBlobby - UniPower, Proof of Liquidity concept:
// https://etherscan.io/address/0xF2f9A7e93f845b3ce154EfbeB64fB9346FCCE509#code
//
//~~~ Dorf - UniBomb V1 and V2, V3 migration
//~~~ Mr Fahrenheit - Most of V3 contract
//~~~ Zoma - Auditing
//~~~ Phil - Design
//~~~ V2 Community - Design and feedback

pragma solidity ^0.5.17;

interface ERC20 {
    function totalSupply() external view returns (uint);
    function balanceOf(address who) external view returns (uint);
    function allowance(address owner, address spender) external view returns (uint);
    function transfer(address to, uint value) external returns (bool);
    function approve(address spender, uint value) external returns (bool);
    function transferFrom(address from, address to, uint value) external returns (bool);
    event Transfer(address indexed from, address indexed to, uint value);
    event Approval(address indexed owner, address indexed spender, uint value);
}

interface ApproveAndCallFallBack {
    function receiveApproval(address from, uint tokens, address token, bytes calldata data) external;
}

interface IUniswapV2Pair {
    function sync() external;
}

contract UniBombV3 is ERC20 {
    using SafeMath for uint;

    modifier initialPhaseOver() {
        require(now > initialPhaseEnd, 'Not yet');
        _;
    }

    modifier unclaimedRewards(address addr) {
        uint rewards = calculateRewards(addr);
        if (rewards > 0) {
            claimRewards(addr, rewards);
        }
        _;
    }

    modifier burnCheck() {
        if (lastPoolBalance != balanceOf(pool)) {
            burnUpdate();
        }
        _;
    }

    struct User {
        uint balance;
        mapping (address => uint) allowed;
        uint allTimeRewards;
        uint stakeBalance;
        int stakePayouts;
    }

    mapping (address => User) internal user;

    address pool;

    // ERC20 stuff
    string public constant name  = "UniBombV3";
    string public constant symbol = "UBOMB";
    uint8 public constant decimals = 18;

    // v2
    ERC20 private ubombv2;

    // burn stuff
    uint lastBurnTime;
    uint toBurn;
    uint day = 86400; // 86400 seconds in one day
    uint burnRate = 3; // 3% burn per day
    uint _totalSupply;
    uint startingSupply = 10000000 * (10 ** 18); // 10 million supply
    uint totalBurned;

    uint lastPoolBalance;

    uint constant private BURN_REWARD = 10;

    // staking stuff
    uint constant private STAKE_FEE = 10;
    uint constant private MAG = 2**64;

    uint internal initialPhaseEnd;
    uint internal totalStaked;
    uint internal divsPerShare;
    bool internal initialized;

    event Stake(address user, uint staked);
    event Unstake(address user, uint unstaked);
    event PoolBurn(address user, uint burned, uint newSupply, uint newPool);

    function() external payable {
        revert('No');
    }

    // For UI

    function allInfoFor(address addr) public view returns (uint, uint, uint, uint, uint, uint, uint, uint, uint, uint) {
        User memory _user = user[addr];
        return (
            _user.balance,
            _user.stakeBalance,
            calculateRewards(addr),
            _user.allTimeRewards,
            user[pool].balance,
            _totalSupply,
            totalStaked,
            totalBurned,
            toBurn,
            lastBurnTime
        );
    }

    // Migration

    function initialize(uint _initialPhaseEnd, uint _poolSupply, address _ubombv2, address _poolAddr) external {
        require(!initialized);
        initialPhaseEnd = _initialPhaseEnd;
        user[msg.sender].balance = _poolSupply;
        _totalSupply = _poolSupply;
        ubombv2 = ERC20(_ubombv2);
        totalBurned = startingSupply - ubombv2.totalSupply();
        pool = _poolAddr;
        lastBurnTime = now;
        initialized = true;
    }

    function receiveApproval(address from, uint tokens, address token, bytes memory data) public {
        require(ubombv2.transferFrom(from, address(this), tokens), 'Transfer failed');
        user[from].balance += tokens;
        _totalSupply += tokens;
        emit Transfer(address(0), msg.sender, tokens);
    }

    // Staking functions

    function distribute(uint amount) public {
        require(totalStaked > 0, 'Stake required');
        User memory _user = user[msg.sender];
        require(_user.balance >= amount, 'Not enough minerals');
        _user.balance = _user.balance.sub(amount);
        user[msg.sender] = _user;

        divsPerShare = divsPerShare.add((amount * MAG) / totalStaked);
    }

    function stake(address addr, uint amount) public unclaimedRewards(msg.sender) {
        require(user[msg.sender].balance >= amount, 'Not enough minerals');
        require(addr != pool, 'Pool cannot stake');
        User memory _user = user[addr];

        if (now < initialPhaseEnd) {
            totalStaked += amount;
            _user.stakeBalance += amount;
            _user.stakePayouts += (int)(divsPerShare.mul(amount));
            user[addr] = _user;
            user[msg.sender].balance = user[msg.sender].balance.sub(amount);
            return;
        }

        uint fee = (amount * STAKE_FEE) / 100;
        uint newStake = amount.sub(fee);
        totalStaked += newStake;
        uint userFeeShare = fee - (fee - (newStake * ((fee * MAG) / totalStaked)));
        divsPerShare = divsPerShare.add((fee * MAG) / totalStaked);

        _user.stakeBalance += newStake;
        _user.stakePayouts += (int)(divsPerShare.mul(newStake).sub(userFeeShare));

        user[addr] = _user;
        user[msg.sender].balance = user[msg.sender].balance.sub(amount);

        emit Stake(addr, amount);
    }

    function unstake(uint amount) public initialPhaseOver {
        address addr = msg.sender;
        User memory _user = user[addr];
        require(amount <= _user.stakeBalance, 'Not enough staked');

        uint fee = (amount * STAKE_FEE) / 100;
        uint received = amount.sub(fee);

        totalStaked = totalStaked.sub(amount);
        _user.stakeBalance -= amount;
        _user.stakePayouts -= (int)(divsPerShare.mul(amount));
        _user.balance += received;

        divsPerShare = divsPerShare.add((fee * MAG).div(totalStaked));

        user[addr] = _user;

        emit Unstake(addr, amount);
    }

    function calculateRewards(address addr) internal view returns (uint) {
        User memory _user = user[addr];
        return (uint)((int)(divsPerShare.mul(_user.stakeBalance)) - _user.stakePayouts) / MAG;
    }

    function claimRewards(address addr, uint rewards) internal {
        User memory _user = user[addr];
        _user.balance += rewards;
        _user.allTimeRewards += rewards;
        _user.stakePayouts += (int)(rewards * MAG);
        user[addr] = _user;
    }

    // ERC20 functions

    function totalSupply() public view returns (uint) {
       return _totalSupply.sub(toBurn + getBurnAmount());
    }

    function balanceOf(address addr) public view returns (uint) {
        return user[addr].balance + calculateRewards(addr);
    }

    function allowance(address addr, address spender) public view returns (uint) {
        return user[addr].allowed[spender];
    }

    function transfer(address to, uint value) public unclaimedRewards(msg.sender) burnCheck returns (bool) {
        User memory _user = user[msg.sender];
        require(_user.balance >= value, 'Not enough minerals');

        _user.balance = _user.balance.sub(value);
        user[msg.sender] = _user;
        user[to].balance += value;

        emit Transfer(msg.sender, to, value);
        return true;
    }

    function approve(address spender, uint value) public returns (bool) {
        user[msg.sender].allowed[spender] = value;
        emit Approval(msg.sender, spender, value);
        return true;
    }

    function approveAndCall(address spender, uint tokens, bytes calldata data) external unclaimedRewards(msg.sender) returns (bool) {
        user[msg.sender].allowed[spender] = tokens;
        emit Approval(msg.sender, spender, tokens);
        ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, address(this), data);
        return true;
    }

    function transferFrom(address from, address to, uint value) public unclaimedRewards(from) burnCheck returns (bool) {
        User storage _user = user[from];
        require(_user.balance >= value, 'Not enough minerals');
        require(_user.allowed[msg.sender] >= value, 'You require more vespene gas');

        _user.balance = _user.balance.sub(value);
        _user.allowed[msg.sender] = _user.allowed[msg.sender].sub(value);
        user[from] = _user;
        user[to].balance += value;

        emit Transfer(from, to, value);
        return true;
    }

    function increaseAllowance(address spender, uint addedValue) public returns (bool) {
        user[msg.sender].allowed[spender] = user[msg.sender].allowed[spender].add(addedValue);
        emit Approval(msg.sender, spender, user[msg.sender].allowed[spender]);
        return true;
    }

    function decreaseAllowance(address spender, uint subtractedValue) public returns (bool) {
        user[msg.sender].allowed[spender] = user[msg.sender].allowed[spender].sub(subtractedValue);
        emit Approval(msg.sender, spender, user[msg.sender].allowed[spender]);
        return true;
    }

    // burn functions

    function burnPool() external {
        require(totalStaked > 0, 'Stake required');
        uint _burnAmount = getBurnAmount() + toBurn;
        require(_burnAmount >= 10, "Nothing to burn...");
        lastBurnTime = now;
        toBurn = 0;

        uint _userReward = _burnAmount * 10 / 100;
        uint _stakeReward = _burnAmount * 20 / 100;
        uint _finalBurn = _burnAmount - _userReward - _stakeReward;

        _totalSupply = _totalSupply.sub(_finalBurn);
        totalBurned += _finalBurn;
        user[msg.sender].balance += _userReward;
        divsPerShare = divsPerShare.add((_stakeReward * MAG) / totalStaked);
        user[pool].balance = user[pool].balance.sub(_finalBurn);

        IUniswapV2Pair(pool).sync();

        emit PoolBurn(msg.sender, _burnAmount, _totalSupply, balanceOf(pool));
    }

    function getBurnAmount() public view returns (uint) {
        uint _time = now - lastBurnTime;
        uint _poolAmount = balanceOf(pool);
        uint _burnAmount = (_poolAmount * burnRate * _time) / (day * 100);
        return _burnAmount;
    }

    function burnUpdate() internal {
        toBurn += getBurnAmount();
        lastBurnTime = now;
        lastPoolBalance = balanceOf(pool);
    }
}

library SafeMath {
    function mul(uint a, uint b) internal pure returns (uint) {
        if (a == 0) {
            return 0;
        }
        uint c = a * b;
        require(c / a == b, "safemath mul");
        return c;
    }
    function div(uint a, uint b) internal pure returns (uint) {
        uint c = a / b;
        return c;
    }
    function sub(uint a, uint b) internal pure returns (uint) {
        require(b <= a, "safemath sub");
        return a - b;
    }
    function add(uint a, uint b) internal pure returns (uint) {
        uint c = a + b;
        require(c >= a, "safemath add");
        return c;
    }
}
设置
{
  "compilationTarget": {
    "UniBombV3.sol": "UniBombV3"
  },
  "evmVersion": "istanbul",
  "libraries": {},
  "optimizer": {
    "enabled": false,
    "runs": 200
  },
  "remappings": []
}
ABI
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"burned","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newPool","type":"uint256"}],"name":"PoolBurn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"staked","type":"uint256"}],"name":"Stake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"unstaked","type":"uint256"}],"name":"Unstake","type":"event"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"constant":true,"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"allInfoFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"tokens","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"approveAndCall","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"burnPool","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"distribute","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getBurnAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_initialPhaseEnd","type":"uint256"},{"internalType":"uint256","name":"_poolSupply","type":"uint256"},{"internalType":"address","name":"_ubombv2","type":"address"},{"internalType":"address","name":"_poolAddr","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"tokens","type":"uint256"},{"internalType":"address","name":"token","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"receiveApproval","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"unstake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]