ETH Price: $1,966.92 (+3.13%)

Transaction Decoder

Block:
10912496 at Sep-22-2020 01:15:23 PM +UTC
Transaction Fee:
0.018979444 ETH $37.33
Gas Used:
114,334 Gas / 166 Gwei

Emitted Events:

300 BPool.Transfer( src=[Receiver] SAFEDaiPool, dst=[Sender] 0xe84e59b58301db0eeaef264e611e9d599dd3d89e, amt=324989810000000000000000 )
301 SAFEDaiPool.Withdrawn( user=[Sender] 0xe84e59b58301db0eeaef264e611e9d599dd3d89e, amount=324989810000000000000000 )
302 SAFE.Transfer( from=[Receiver] SAFEDaiPool, to=[Sender] 0xe84e59b58301db0eeaef264e611e9d599dd3d89e, value=402916903128607756 )
303 SAFEDaiPool.RewardPaid( user=[Sender] 0xe84e59b58301db0eeaef264e611e9d599dd3d89e, reward=402916903128607756 )

Account State Difference:

  Address   Before After State Difference Code
0x1Aa61c19...Ed24FC469
0x3031745E...a18F1012d
0x668d0527...7e253eaf9
(YieldFarming.insure: Balancer Pool)
(F2Pool Old)
7,897.358242973134584332 Eth7,897.377222417134584332 Eth0.018979444
0xe84E59B5...99DD3D89e
2.069904376313715967 Eth
Nonce: 568
2.050924932313715967 Eth
Nonce: 569
0.018979444

Execution Trace

SAFEDaiPool.CALL( )
  • BPool.transfer( dst=0xe84E59B58301dB0eeaEf264E611E9d599DD3D89e, amt=324989810000000000000000 ) => ( True )
  • SAFE.transfer( recipient=0xe84E59B58301dB0eeaEf264E611E9d599DD3D89e, amount=402916903128607756 ) => ( True )
    File 1 of 3: SAFEDaiPool
    /**
     *Submitted for verification at Etherscan.io on 2020-07-31
    */
    
    /*
       ____            __   __        __   _
      / __/__ __ ___  / /_ / /  ___  / /_ (_)__ __
     _\ \ / // // _ \/ __// _ \/ -_)/ __// / \ \ /
    /___/ \_, //_//_/\__//_//_/\__/ \__//_/ /_\_\
         /___/
    
    * Synthetix: YFIRewards.sol
    *
    * Docs: https://docs.synthetix.io/
    *
    *
    * MIT License
    * ===========
    *
    * Copyright (c) 2020 Synthetix
    *
    * Permission is hereby granted, free of charge, to any person obtaining a copy
    * of this software and associated documentation files (the "Software"), to deal
    * in the Software without restriction, including without limitation the rights
    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    * copies of the Software, and to permit persons to whom the Software is
    * furnished to do so, subject to the following conditions:
    *
    * The above copyright notice and this permission notice shall be included in all
    * copies or substantial portions of the Software.
    *
    * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    */
    
    // File: @openzeppelin/contracts/math/Math.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @dev Standard math utilities missing in the Solidity language.
     */
    library Math {
        /**
         * @dev Returns the largest of two numbers.
         */
        function max(uint256 a, uint256 b) internal pure returns (uint256) {
            return a >= b ? a : b;
        }
    
        /**
         * @dev Returns the smallest of two numbers.
         */
        function min(uint256 a, uint256 b) internal pure returns (uint256) {
            return a < b ? a : b;
        }
    
        /**
         * @dev Returns the average of two numbers. The result is rounded towards
         * zero.
         */
        function average(uint256 a, uint256 b) internal pure returns (uint256) {
            // (a + b) / 2 can overflow, so we distribute
            return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
        }
    }
    
    // File: @openzeppelin/contracts/math/SafeMath.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @dev Wrappers over Solidity's arithmetic operations with added overflow
     * checks.
     *
     * Arithmetic operations in Solidity wrap on overflow. This can easily result
     * in bugs, because programmers usually assume that an overflow raises an
     * error, which is the standard behavior in high level programming languages.
     * `SafeMath` restores this intuition by reverting the transaction when an
     * operation overflows.
     *
     * Using this library instead of the unchecked operations eliminates an entire
     * class of bugs, so it's recommended to use it always.
     */
    library SafeMath {
        /**
         * @dev Returns the addition of two unsigned integers, reverting on
         * overflow.
         *
         * Counterpart to Solidity's `+` operator.
         *
         * Requirements:
         * - Addition cannot overflow.
         */
        function add(uint256 a, uint256 b) internal pure returns (uint256) {
            uint256 c = a + b;
            require(c >= a, "SafeMath: addition overflow");
    
            return c;
        }
    
        /**
         * @dev Returns the subtraction of two unsigned integers, reverting on
         * overflow (when the result is negative).
         *
         * Counterpart to Solidity's `-` operator.
         *
         * Requirements:
         * - Subtraction cannot overflow.
         */
        function sub(uint256 a, uint256 b) internal pure returns (uint256) {
            return sub(a, b, "SafeMath: subtraction overflow");
        }
    
        /**
         * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
         * overflow (when the result is negative).
         *
         * Counterpart to Solidity's `-` operator.
         *
         * Requirements:
         * - Subtraction cannot overflow.
         *
         * _Available since v2.4.0._
         */
        function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
            require(b <= a, errorMessage);
            uint256 c = a - b;
    
            return c;
        }
    
        /**
         * @dev Returns the multiplication of two unsigned integers, reverting on
         * overflow.
         *
         * Counterpart to Solidity's `*` operator.
         *
         * Requirements:
         * - Multiplication cannot overflow.
         */
        function mul(uint256 a, uint256 b) internal pure returns (uint256) {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) {
                return 0;
            }
    
            uint256 c = a * b;
            require(c / a == b, "SafeMath: multiplication overflow");
    
            return c;
        }
    
        /**
         * @dev Returns the integer division of two unsigned integers. Reverts on
         * division by zero. The result is rounded towards zero.
         *
         * Counterpart to Solidity's `/` operator. Note: this function uses a
         * `revert` opcode (which leaves remaining gas untouched) while Solidity
         * uses an invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         * - The divisor cannot be zero.
         */
        function div(uint256 a, uint256 b) internal pure returns (uint256) {
            return div(a, b, "SafeMath: division by zero");
        }
    
        /**
         * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
         * division by zero. The result is rounded towards zero.
         *
         * Counterpart to Solidity's `/` operator. Note: this function uses a
         * `revert` opcode (which leaves remaining gas untouched) while Solidity
         * uses an invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         * - The divisor cannot be zero.
         *
         * _Available since v2.4.0._
         */
        function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
            // Solidity only automatically asserts when dividing by 0
            require(b > 0, errorMessage);
            uint256 c = a / b;
            // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    
            return c;
        }
    
        /**
         * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
         * Reverts when dividing by zero.
         *
         * Counterpart to Solidity's `%` operator. This function uses a `revert`
         * opcode (which leaves remaining gas untouched) while Solidity uses an
         * invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         * - The divisor cannot be zero.
         */
        function mod(uint256 a, uint256 b) internal pure returns (uint256) {
            return mod(a, b, "SafeMath: modulo by zero");
        }
    
        /**
         * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
         * Reverts with custom message when dividing by zero.
         *
         * Counterpart to Solidity's `%` operator. This function uses a `revert`
         * opcode (which leaves remaining gas untouched) while Solidity uses an
         * invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         * - The divisor cannot be zero.
         *
         * _Available since v2.4.0._
         */
        function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
            require(b != 0, errorMessage);
            return a % b;
        }
    }
    
    // File: @openzeppelin/contracts/GSN/Context.sol
    
    pragma solidity ^0.5.0;
    
    /*
     * @dev Provides information about the current execution context, including the
     * sender of the transaction and its data. While these are generally available
     * via msg.sender and msg.data, they should not be accessed in such a direct
     * manner, since when dealing with GSN meta-transactions the account sending and
     * paying for execution may not be the actual sender (as far as an application
     * is concerned).
     *
     * This contract is only required for intermediate, library-like contracts.
     */
    contract Context {
        // Empty internal constructor, to prevent people from mistakenly deploying
        // an instance of this contract, which should be used via inheritance.
        constructor () internal { }
        // solhint-disable-previous-line no-empty-blocks
    
        function _msgSender() internal view returns (address payable) {
            return msg.sender;
        }
    
        function _msgData() internal view returns (bytes memory) {
            this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
            return msg.data;
        }
    }
    
    // File: @openzeppelin/contracts/ownership/Ownable.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @dev Contract module which provides a basic access control mechanism, where
     * there is an account (an owner) that can be granted exclusive access to
     * specific functions.
     *
     * This module is used through inheritance. It will make available the modifier
     * `onlyOwner`, which can be applied to your functions to restrict their use to
     * the owner.
     */
    contract Ownable is Context {
        address private _owner;
    
        event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    
        /**
         * @dev Initializes the contract setting the deployer as the initial owner.
         */
        constructor () internal {
            _owner = _msgSender();
            emit OwnershipTransferred(address(0), _owner);
        }
    
        /**
         * @dev Returns the address of the current owner.
         */
        function owner() public view returns (address) {
            return _owner;
        }
    
        /**
         * @dev Throws if called by any account other than the owner.
         */
        modifier onlyOwner() {
            require(isOwner(), "Ownable: caller is not the owner");
            _;
        }
    
        /**
         * @dev Returns true if the caller is the current owner.
         */
        function isOwner() public view returns (bool) {
            return _msgSender() == _owner;
        }
    
        /**
         * @dev Leaves the contract without owner. It will not be possible to call
         * `onlyOwner` functions anymore. Can only be called by the current owner.
         *
         * NOTE: Renouncing ownership will leave the contract without an owner,
         * thereby removing any functionality that is only available to the owner.
         */
        function renounceOwnership() public onlyOwner {
            emit OwnershipTransferred(_owner, address(0));
            _owner = address(0);
        }
    
        /**
         * @dev Transfers ownership of the contract to a new account (`newOwner`).
         * Can only be called by the current owner.
         */
        function transferOwnership(address newOwner) public onlyOwner {
            _transferOwnership(newOwner);
        }
    
        /**
         * @dev Transfers ownership of the contract to a new account (`newOwner`).
         */
        function _transferOwnership(address newOwner) internal {
            require(newOwner != address(0), "Ownable: new owner is the zero address");
            emit OwnershipTransferred(_owner, newOwner);
            _owner = newOwner;
        }
    }
    
    // File: @openzeppelin/contracts/token/ERC20/IERC20.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
     * the optional functions; to access them see {ERC20Detailed}.
     */
    interface IERC20 {
        /**
         * @dev Returns the amount of tokens in existence.
         */
        function totalSupply() external view returns (uint256);
    
        /**
         * @dev Returns the amount of tokens owned by `account`.
         */
        function balanceOf(address account) external view returns (uint256);
    
        /**
         * @dev Moves `amount` tokens from the caller's account to `recipient`.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * Emits a {Transfer} event.
         */
        function transfer(address recipient, uint256 amount) external returns (bool);
        function mint(address account, uint amount) external;
    
        /**
         * @dev Returns the remaining number of tokens that `spender` will be
         * allowed to spend on behalf of `owner` through {transferFrom}. This is
         * zero by default.
         *
         * This value changes when {approve} or {transferFrom} are called.
         */
        function allowance(address owner, address spender) external view returns (uint256);
    
        /**
         * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * IMPORTANT: Beware that changing an allowance with this method brings the risk
         * that someone may use both the old and the new allowance by unfortunate
         * transaction ordering. One possible solution to mitigate this race
         * condition is to first reduce the spender's allowance to 0 and set the
         * desired value afterwards:
         * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
         *
         * Emits an {Approval} event.
         */
        function approve(address spender, uint256 amount) external returns (bool);
    
        /**
         * @dev Moves `amount` tokens from `sender` to `recipient` using the
         * allowance mechanism. `amount` is then deducted from the caller's
         * allowance.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * Emits a {Transfer} event.
         */
        function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
    
        /**
         * @dev Emitted when `value` tokens are moved from one account (`from`) to
         * another (`to`).
         *
         * Note that `value` may be zero.
         */
        event Transfer(address indexed from, address indexed to, uint256 value);
    
        /**
         * @dev Emitted when the allowance of a `spender` for an `owner` is set by
         * a call to {approve}. `value` is the new allowance.
         */
        event Approval(address indexed owner, address indexed spender, uint256 value);
    }
    
    // File: @openzeppelin/contracts/utils/Address.sol
    
    pragma solidity ^0.5.5;
    
    /**
     * @dev Collection of functions related to the address type
     */
    library Address {
        /**
         * @dev Returns true if `account` is a contract.
         *
         * This test is non-exhaustive, and there may be false-negatives: during the
         * execution of a contract's constructor, its address will be reported as
         * not containing a contract.
         *
         * IMPORTANT: It is unsafe to assume that an address for which this
         * function returns false is an externally-owned account (EOA) and not a
         * contract.
         */
        function isContract(address account) internal view returns (bool) {
            // This method relies in extcodesize, which returns 0 for contracts in
            // construction, since the code is only stored at the end of the
            // constructor execution.
    
            // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
            // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
            // for accounts without code, i.e. `keccak256('')`
            bytes32 codehash;
            bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
            // solhint-disable-next-line no-inline-assembly
            assembly { codehash := extcodehash(account) }
            return (codehash != 0x0 && codehash != accountHash);
        }
    
        /**
         * @dev Converts an `address` into `address payable`. Note that this is
         * simply a type cast: the actual underlying value is not changed.
         *
         * _Available since v2.4.0._
         */
        function toPayable(address account) internal pure returns (address payable) {
            return address(uint160(account));
        }
    
        /**
         * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
         * `recipient`, forwarding all available gas and reverting on errors.
         *
         * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
         * of certain opcodes, possibly making contracts go over the 2300 gas limit
         * imposed by `transfer`, making them unable to receive funds via
         * `transfer`. {sendValue} removes this limitation.
         *
         * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
         *
         * IMPORTANT: because control is transferred to `recipient`, care must be
         * taken to not create reentrancy vulnerabilities. Consider using
         * {ReentrancyGuard} or the
         * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
         *
         * _Available since v2.4.0._
         */
        function sendValue(address payable recipient, uint256 amount) internal {
            require(address(this).balance >= amount, "Address: insufficient balance");
    
            // solhint-disable-next-line avoid-call-value
            (bool success, ) = recipient.call.value(amount)("");
            require(success, "Address: unable to send value, recipient may have reverted");
        }
    }
    
    // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol
    
    pragma solidity ^0.5.0;
    
    
    
    
    /**
     * @title SafeERC20
     * @dev Wrappers around ERC20 operations that throw on failure (when the token
     * contract returns false). Tokens that return no value (and instead revert or
     * throw on failure) are also supported, non-reverting calls are assumed to be
     * successful.
     * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
     * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
     */
    library SafeERC20 {
        using SafeMath for uint256;
        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 {
            // safeApprove should only be called when setting an initial allowance,
            // or when resetting it to zero. To increase and decrease it, use
            // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
            // solhint-disable-next-line max-line-length
            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).add(value);
            callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    
        function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
            uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
            callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    
        /**
         * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
         * on the return value: the return value is optional (but if data is returned, it must not be false).
         * @param token The token targeted by the call.
         * @param data The call data (encoded using abi.encode or one of its variants).
         */
        function callOptionalReturn(IERC20 token, bytes memory data) private {
            // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
            // we're implementing it ourselves.
    
            // A Solidity high level call has three parts:
            //  1. The target address is checked to verify it contains contract code
            //  2. The call itself is made, and success asserted
            //  3. The return value is decoded, which in turn checks the size of the returned data.
            // solhint-disable-next-line max-line-length
            require(address(token).isContract(), "SafeERC20: call to non-contract");
    
            // solhint-disable-next-line avoid-low-level-calls
            (bool success, bytes memory returndata) = address(token).call(data);
            require(success, "SafeERC20: low-level call failed");
    
            if (returndata.length > 0) { // Return data is optional
                // solhint-disable-next-line max-line-length
                require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
            }
        }
    }
    
    // File: contracts/IRewardDistributionRecipient.sol
    
    pragma solidity ^0.5.0;
    
    
    
    contract IRewardDistributionRecipient is Ownable {
        address rewardDistribution;
    
        function notifyRewardAmount(uint256 reward) external;
    
        modifier onlyRewardDistribution() {
            require(_msgSender() == rewardDistribution, "Caller is not reward distribution");
            _;
        }
    
        function setRewardDistribution(address _rewardDistribution)
            external
            onlyOwner
        {
            rewardDistribution = _rewardDistribution;
        }
    }
    
    
    pragma solidity ^0.5.0;
    
    contract LPTokenWrapper {
        using SafeMath for uint256;
        using SafeERC20 for IERC20;
    
        IERC20 public bpt_safe_dai = IERC20(0x3031745E732dcE8fECccc94AcA13D5fa18F1012d);
    
        uint256 private _totalSupply;
        mapping(address => uint256) private _balances;
    
        function totalSupply() public view returns (uint256) {
            return _totalSupply;
        }
    
        function balanceOf(address account) public view returns (uint256) {
            return _balances[account];
        }
    
        function stake(uint256 amount) public {
            _totalSupply = _totalSupply.add(amount);
            _balances[msg.sender] = _balances[msg.sender].add(amount);
            bpt_safe_dai.safeTransferFrom(msg.sender, address(this), amount);
        }
    
        function withdraw(uint256 amount) public {
            _totalSupply = _totalSupply.sub(amount);
            _balances[msg.sender] = _balances[msg.sender].sub(amount);
            bpt_safe_dai.safeTransfer(msg.sender, amount);
        }
    }
    
    contract SAFEDaiPool is LPTokenWrapper, IRewardDistributionRecipient {
        IERC20 public safe = IERC20(0x1Aa61c196E76805fcBe394eA00e4fFCEd24FC469);
        uint256 public constant DURATION = 7 days;
    
        uint256 public initreward = 10000*1e18;
        uint256 public starttime = 1600030800; //Sunday, September 13, 2020 4:00:00 PM GMT-05:00 DST
        uint256 public periodFinish = 0;
        uint256 public rewardRate = 0;
        uint256 public lastUpdateTime;
        uint256 public rewardPerTokenStored;
        mapping(address => uint256) public userRewardPerTokenPaid;
        mapping(address => uint256) public rewards;
    
        event RewardAdded(uint256 reward);
        event Staked(address indexed user, uint256 amount);
        event Withdrawn(address indexed user, uint256 amount);
        event RewardPaid(address indexed user, uint256 reward);
    
        modifier updateReward(address account) {
            rewardPerTokenStored = rewardPerToken();
            lastUpdateTime = lastTimeRewardApplicable();
            if (account != address(0)) {
                rewards[account] = earned(account);
                userRewardPerTokenPaid[account] = rewardPerTokenStored;
            }
            _;
        }
    
        function lastTimeRewardApplicable() public view returns (uint256) {
            return Math.min(block.timestamp, periodFinish);
        }
    
        function rewardPerToken() public view returns (uint256) {
            if (totalSupply() == 0) {
                return rewardPerTokenStored;
            }
            return
                rewardPerTokenStored.add(
                    lastTimeRewardApplicable()
                        .sub(lastUpdateTime)
                        .mul(rewardRate)
                        .mul(1e18)
                        .div(totalSupply())
                );
        }
    
        function earned(address account) public view returns (uint256) {
            return
                balanceOf(account)
                    .mul(rewardPerToken().sub(userRewardPerTokenPaid[account]))
                    .div(1e18)
                    .add(rewards[account]);
        }
    
        // stake visibility is public as overriding LPTokenWrapper's stake() function
        function stake(uint256 amount) public updateReward(msg.sender) checkhalve checkStart{ 
            require(amount > 0, "Cannot stake 0");
            super.stake(amount);
            emit Staked(msg.sender, amount);
        }
    
        function withdraw(uint256 amount) public updateReward(msg.sender) checkStart{
            require(amount > 0, "Cannot withdraw 0");
            super.withdraw(amount);
            emit Withdrawn(msg.sender, amount);
        }
    
        function exit() external {
            withdraw(balanceOf(msg.sender));
            getReward();
        }
    
        function getReward() public updateReward(msg.sender) checkhalve checkStart{
            uint256 reward = earned(msg.sender);
            if (reward > 0) {
                rewards[msg.sender] = 0;
                safe.safeTransfer(msg.sender, reward);
                emit RewardPaid(msg.sender, reward);
            }
        }
    
        modifier checkhalve(){
            if (block.timestamp >= periodFinish) {
                initreward = initreward.mul(50).div(100); 
                safe.mint(address(this),initreward);
    
                rewardRate = initreward.div(DURATION);
                periodFinish = block.timestamp.add(DURATION);
                emit RewardAdded(initreward);
            }
            _;
        }
        modifier checkStart(){
            require(block.timestamp > starttime,"not start");
            _;
        }
    
        function notifyRewardAmount(uint256 reward)
            external
            onlyRewardDistribution
            updateReward(address(0))
        {
            if (block.timestamp >= periodFinish) {
                rewardRate = reward.div(DURATION);
            } else {
                uint256 remaining = periodFinish.sub(block.timestamp);
                uint256 leftover = remaining.mul(rewardRate);
                rewardRate = reward.add(leftover).div(DURATION);
            }
            safe.mint(address(this),reward);
            lastUpdateTime = block.timestamp;
            periodFinish = block.timestamp.add(DURATION);
            emit RewardAdded(reward);
        }
    }

    File 2 of 3: BPool
    {"BColor.sol":{"content":"// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see \u003chttp://www.gnu.org/licenses/\u003e.\n\npragma solidity 0.5.12;\n\ncontract BColor {\n    function getColor()\n        external view\n        returns (bytes32);\n}\n\ncontract BBronze is BColor {\n    function getColor()\n        external view\n        returns (bytes32) {\n            return bytes32(\"BRONZE\");\n        }\n}\n"},"BConst.sol":{"content":"// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see \u003chttp://www.gnu.org/licenses/\u003e.\n\npragma solidity 0.5.12;\n\nimport \"./BColor.sol\";\n\ncontract BConst is BBronze {\n    uint public constant BONE              = 10**18;\n\n    uint public constant MIN_BOUND_TOKENS  = 2;\n    uint public constant MAX_BOUND_TOKENS  = 8;\n\n    uint public constant MIN_FEE           = BONE / 10**6;\n    uint public constant MAX_FEE           = BONE / 10;\n    uint public constant EXIT_FEE          = 0;\n\n    uint public constant MIN_WEIGHT        = BONE;\n    uint public constant MAX_WEIGHT        = BONE * 50;\n    uint public constant MAX_TOTAL_WEIGHT  = BONE * 50;\n    uint public constant MIN_BALANCE       = BONE / 10**12;\n\n    uint public constant INIT_POOL_SUPPLY  = BONE * 100;\n\n    uint public constant MIN_BPOW_BASE     = 1 wei;\n    uint public constant MAX_BPOW_BASE     = (2 * BONE) - 1 wei;\n    uint public constant BPOW_PRECISION    = BONE / 10**10;\n\n    uint public constant MAX_IN_RATIO      = BONE / 2;\n    uint public constant MAX_OUT_RATIO     = (BONE / 3) + 1 wei;\n}\n"},"BMath.sol":{"content":"// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see \u003chttp://www.gnu.org/licenses/\u003e.\n\npragma solidity 0.5.12;\n\nimport \"./BNum.sol\";\n\ncontract BMath is BBronze, BConst, BNum {\n    /**********************************************************************************************\n    // calcSpotPrice                                                                             //\n    // sP = spotPrice                                                                            //\n    // bI = tokenBalanceIn                ( bI / wI )         1                                  //\n    // bO = tokenBalanceOut         sP =  -----------  *  ----------                             //\n    // wI = tokenWeightIn                 ( bO / wO )     ( 1 - sF )                             //\n    // wO = tokenWeightOut                                                                       //\n    // sF = swapFee                                                                              //\n    **********************************************************************************************/\n    function calcSpotPrice(\n        uint tokenBalanceIn,\n        uint tokenWeightIn,\n        uint tokenBalanceOut,\n        uint tokenWeightOut,\n        uint swapFee\n    )\n        public pure\n        returns (uint spotPrice)\n    {\n        uint numer = bdiv(tokenBalanceIn, tokenWeightIn);\n        uint denom = bdiv(tokenBalanceOut, tokenWeightOut);\n        uint ratio = bdiv(numer, denom);\n        uint scale = bdiv(BONE, bsub(BONE, swapFee));\n        return  (spotPrice = bmul(ratio, scale));\n    }\n\n    /**********************************************************************************************\n    // calcOutGivenIn                                                                            //\n    // aO = tokenAmountOut                                                                       //\n    // bO = tokenBalanceOut                                                                      //\n    // bI = tokenBalanceIn              /      /            bI             \\    (wI / wO) \\      //\n    // aI = tokenAmountIn    aO = bO * |  1 - | --------------------------  | ^            |     //\n    // wI = tokenWeightIn               \\      \\ ( bI + ( aI * ( 1 - sF )) /              /      //\n    // wO = tokenWeightOut                                                                       //\n    // sF = swapFee                                                                              //\n    **********************************************************************************************/\n    function calcOutGivenIn(\n        uint tokenBalanceIn,\n        uint tokenWeightIn,\n        uint tokenBalanceOut,\n        uint tokenWeightOut,\n        uint tokenAmountIn,\n        uint swapFee\n    )\n        public pure\n        returns (uint tokenAmountOut)\n    {\n        uint weightRatio = bdiv(tokenWeightIn, tokenWeightOut);\n        uint adjustedIn = bsub(BONE, swapFee);\n        adjustedIn = bmul(tokenAmountIn, adjustedIn);\n        uint y = bdiv(tokenBalanceIn, badd(tokenBalanceIn, adjustedIn));\n        uint foo = bpow(y, weightRatio);\n        uint bar = bsub(BONE, foo);\n        tokenAmountOut = bmul(tokenBalanceOut, bar);\n        return tokenAmountOut;\n    }\n\n    /**********************************************************************************************\n    // calcInGivenOut                                                                            //\n    // aI = tokenAmountIn                                                                        //\n    // bO = tokenBalanceOut               /  /     bO      \\    (wO / wI)      \\                 //\n    // bI = tokenBalanceIn          bI * |  | ------------  | ^            - 1  |                //\n    // aO = tokenAmountOut    aI =        \\  \\ ( bO - aO ) /                   /                 //\n    // wI = tokenWeightIn           --------------------------------------------                 //\n    // wO = tokenWeightOut                          ( 1 - sF )                                   //\n    // sF = swapFee                                                                              //\n    **********************************************************************************************/\n    function calcInGivenOut(\n        uint tokenBalanceIn,\n        uint tokenWeightIn,\n        uint tokenBalanceOut,\n        uint tokenWeightOut,\n        uint tokenAmountOut,\n        uint swapFee\n    )\n        public pure\n        returns (uint tokenAmountIn)\n    {\n        uint weightRatio = bdiv(tokenWeightOut, tokenWeightIn);\n        uint diff = bsub(tokenBalanceOut, tokenAmountOut);\n        uint y = bdiv(tokenBalanceOut, diff);\n        uint foo = bpow(y, weightRatio);\n        foo = bsub(foo, BONE);\n        tokenAmountIn = bsub(BONE, swapFee);\n        tokenAmountIn = bdiv(bmul(tokenBalanceIn, foo), tokenAmountIn);\n        return tokenAmountIn;\n    }\n\n    /**********************************************************************************************\n    // calcPoolOutGivenSingleIn                                                                  //\n    // pAo = poolAmountOut         /                                              \\              //\n    // tAi = tokenAmountIn        ///      /     //    wI \\      \\\\       \\     wI \\             //\n    // wI = tokenWeightIn        //| tAi *| 1 - || 1 - --  | * sF || + tBi \\    --  \\            //\n    // tW = totalWeight     pAo=||  \\      \\     \\\\    tW /      //         | ^ tW   | * pS - pS //\n    // tBi = tokenBalanceIn      \\\\  ------------------------------------- /        /            //\n    // pS = poolSupply            \\\\                    tBi               /        /             //\n    // sF = swapFee                \\                                              /              //\n    **********************************************************************************************/\n    function calcPoolOutGivenSingleIn(\n        uint tokenBalanceIn,\n        uint tokenWeightIn,\n        uint poolSupply,\n        uint totalWeight,\n        uint tokenAmountIn,\n        uint swapFee\n    )\n        public pure\n        returns (uint poolAmountOut)\n    {\n        // Charge the trading fee for the proportion of tokenAi\n        ///  which is implicitly traded to the other pool tokens.\n        // That proportion is (1- weightTokenIn)\n        // tokenAiAfterFee = tAi * (1 - (1-weightTi) * poolFee);\n        uint normalizedWeight = bdiv(tokenWeightIn, totalWeight);\n        uint zaz = bmul(bsub(BONE, normalizedWeight), swapFee); \n        uint tokenAmountInAfterFee = bmul(tokenAmountIn, bsub(BONE, zaz));\n\n        uint newTokenBalanceIn = badd(tokenBalanceIn, tokenAmountInAfterFee);\n        uint tokenInRatio = bdiv(newTokenBalanceIn, tokenBalanceIn);\n\n        // uint newPoolSupply = (ratioTi ^ weightTi) * poolSupply;\n        uint poolRatio = bpow(tokenInRatio, normalizedWeight);\n        uint newPoolSupply = bmul(poolRatio, poolSupply);\n        poolAmountOut = bsub(newPoolSupply, poolSupply);\n        return poolAmountOut;\n    }\n\n    /**********************************************************************************************\n    // calcSingleInGivenPoolOut                                                                  //\n    // tAi = tokenAmountIn              //(pS + pAo)\\     /    1    \\\\                           //\n    // pS = poolSupply                 || ---------  | ^ | --------- || * bI - bI                //\n    // pAo = poolAmountOut              \\\\    pS    /     \\(wI / tW)//                           //\n    // bI = balanceIn          tAi =  --------------------------------------------               //\n    // wI = weightIn                              /      wI  \\                                   //\n    // tW = totalWeight                          |  1 - ----  |  * sF                            //\n    // sF = swapFee                               \\      tW  /                                   //\n    **********************************************************************************************/\n    function calcSingleInGivenPoolOut(\n        uint tokenBalanceIn,\n        uint tokenWeightIn,\n        uint poolSupply,\n        uint totalWeight,\n        uint poolAmountOut,\n        uint swapFee\n    )\n        public pure\n        returns (uint tokenAmountIn)\n    {\n        uint normalizedWeight = bdiv(tokenWeightIn, totalWeight);\n        uint newPoolSupply = badd(poolSupply, poolAmountOut);\n        uint poolRatio = bdiv(newPoolSupply, poolSupply);\n      \n        //uint newBalTi = poolRatio^(1/weightTi) * balTi;\n        uint boo = bdiv(BONE, normalizedWeight); \n        uint tokenInRatio = bpow(poolRatio, boo);\n        uint newTokenBalanceIn = bmul(tokenInRatio, tokenBalanceIn);\n        uint tokenAmountInAfterFee = bsub(newTokenBalanceIn, tokenBalanceIn);\n        // Do reverse order of fees charged in joinswap_ExternAmountIn, this way \n        //     ``` pAo == joinswap_ExternAmountIn(Ti, joinswap_PoolAmountOut(pAo, Ti)) ```\n        //uint tAi = tAiAfterFee / (1 - (1-weightTi) * swapFee) ;\n        uint zar = bmul(bsub(BONE, normalizedWeight), swapFee);\n        tokenAmountIn = bdiv(tokenAmountInAfterFee, bsub(BONE, zar));\n        return tokenAmountIn;\n    }\n\n    /**********************************************************************************************\n    // calcSingleOutGivenPoolIn                                                                  //\n    // tAo = tokenAmountOut            /      /                                             \\\\   //\n    // bO = tokenBalanceOut           /      // pS - (pAi * (1 - eF)) \\     /    1    \\      \\\\  //\n    // pAi = poolAmountIn            | bO - || ----------------------- | ^ | --------- | * b0 || //\n    // ps = poolSupply                \\      \\\\          pS           /     \\(wO / tW)/      //  //\n    // wI = tokenWeightIn      tAo =   \\      \\                                             //   //\n    // tW = totalWeight                    /     /      wO \\       \\                             //\n    // sF = swapFee                    *  | 1 - |  1 - ---- | * sF  |                            //\n    // eF = exitFee                        \\     \\      tW /       /                             //\n    **********************************************************************************************/\n    function calcSingleOutGivenPoolIn(\n        uint tokenBalanceOut,\n        uint tokenWeightOut,\n        uint poolSupply,\n        uint totalWeight,\n        uint poolAmountIn,\n        uint swapFee\n    )\n        public pure\n        returns (uint tokenAmountOut)\n    {\n        uint normalizedWeight = bdiv(tokenWeightOut, totalWeight);\n        // charge exit fee on the pool token side\n        // pAiAfterExitFee = pAi*(1-exitFee)\n        uint poolAmountInAfterExitFee = bmul(poolAmountIn, bsub(BONE, EXIT_FEE));\n        uint newPoolSupply = bsub(poolSupply, poolAmountInAfterExitFee);\n        uint poolRatio = bdiv(newPoolSupply, poolSupply);\n     \n        // newBalTo = poolRatio^(1/weightTo) * balTo;\n        uint tokenOutRatio = bpow(poolRatio, bdiv(BONE, normalizedWeight));\n        uint newTokenBalanceOut = bmul(tokenOutRatio, tokenBalanceOut);\n\n        uint tokenAmountOutBeforeSwapFee = bsub(tokenBalanceOut, newTokenBalanceOut);\n\n        // charge swap fee on the output token side \n        //uint tAo = tAoBeforeSwapFee * (1 - (1-weightTo) * swapFee)\n        uint zaz = bmul(bsub(BONE, normalizedWeight), swapFee); \n        tokenAmountOut = bmul(tokenAmountOutBeforeSwapFee, bsub(BONE, zaz));\n        return tokenAmountOut;\n    }\n\n    /**********************************************************************************************\n    // calcPoolInGivenSingleOut                                                                  //\n    // pAi = poolAmountIn               // /               tAo             \\\\     / wO \\     \\   //\n    // bO = tokenBalanceOut            // | bO - -------------------------- |\\   | ---- |     \\  //\n    // tAo = tokenAmountOut      pS - ||   \\     1 - ((1 - (tO / tW)) * sF)/  | ^ \\ tW /  * pS | //\n    // ps = poolSupply                 \\\\ -----------------------------------/                /  //\n    // wO = tokenWeightOut  pAi =       \\\\               bO                 /                /   //\n    // tW = totalWeight           -------------------------------------------------------------  //\n    // sF = swapFee                                        ( 1 - eF )                            //\n    // eF = exitFee                                                                              //\n    **********************************************************************************************/\n    function calcPoolInGivenSingleOut(\n        uint tokenBalanceOut,\n        uint tokenWeightOut,\n        uint poolSupply,\n        uint totalWeight,\n        uint tokenAmountOut,\n        uint swapFee\n    )\n        public pure\n        returns (uint poolAmountIn)\n    {\n\n        // charge swap fee on the output token side \n        uint normalizedWeight = bdiv(tokenWeightOut, totalWeight);\n        //uint tAoBeforeSwapFee = tAo / (1 - (1-weightTo) * swapFee) ;\n        uint zoo = bsub(BONE, normalizedWeight);\n        uint zar = bmul(zoo, swapFee); \n        uint tokenAmountOutBeforeSwapFee = bdiv(tokenAmountOut, bsub(BONE, zar));\n\n        uint newTokenBalanceOut = bsub(tokenBalanceOut, tokenAmountOutBeforeSwapFee);\n        uint tokenOutRatio = bdiv(newTokenBalanceOut, tokenBalanceOut);\n\n        //uint newPoolSupply = (ratioTo ^ weightTo) * poolSupply;\n        uint poolRatio = bpow(tokenOutRatio, normalizedWeight);\n        uint newPoolSupply = bmul(poolRatio, poolSupply);\n        uint poolAmountInAfterExitFee = bsub(poolSupply, newPoolSupply);\n\n        // charge exit fee on the pool token side\n        // pAi = pAiAfterExitFee/(1-exitFee)\n        poolAmountIn = bdiv(poolAmountInAfterExitFee, bsub(BONE, EXIT_FEE));\n        return poolAmountIn;\n    }\n\n\n}\n"},"BNum.sol":{"content":"// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see \u003chttp://www.gnu.org/licenses/\u003e.\n\npragma solidity 0.5.12;\n\nimport \"./BConst.sol\";\n\ncontract BNum is BConst {\n\n    function btoi(uint a)\n        internal pure \n        returns (uint)\n    {\n        return a / BONE;\n    }\n\n    function bfloor(uint a)\n        internal pure\n        returns (uint)\n    {\n        return btoi(a) * BONE;\n    }\n\n    function badd(uint a, uint b)\n        internal pure\n        returns (uint)\n    {\n        uint c = a + b;\n        require(c \u003e= a, \"ERR_ADD_OVERFLOW\");\n        return c;\n    }\n\n    function bsub(uint a, uint b)\n        internal pure\n        returns (uint)\n    {\n        (uint c, bool flag) = bsubSign(a, b);\n        require(!flag, \"ERR_SUB_UNDERFLOW\");\n        return c;\n    }\n\n    function bsubSign(uint a, uint b)\n        internal pure\n        returns (uint, bool)\n    {\n        if (a \u003e= b) {\n            return (a - b, false);\n        } else {\n            return (b - a, true);\n        }\n    }\n\n    function bmul(uint a, uint b)\n        internal pure\n        returns (uint)\n    {\n        uint c0 = a * b;\n        require(a == 0 || c0 / a == b, \"ERR_MUL_OVERFLOW\");\n        uint c1 = c0 + (BONE / 2);\n        require(c1 \u003e= c0, \"ERR_MUL_OVERFLOW\");\n        uint c2 = c1 / BONE;\n        return c2;\n    }\n\n    function bdiv(uint a, uint b)\n        internal pure\n        returns (uint)\n    {\n        require(b != 0, \"ERR_DIV_ZERO\");\n        uint c0 = a * BONE;\n        require(a == 0 || c0 / a == BONE, \"ERR_DIV_INTERNAL\"); // bmul overflow\n        uint c1 = c0 + (b / 2);\n        require(c1 \u003e= c0, \"ERR_DIV_INTERNAL\"); //  badd require\n        uint c2 = c1 / b;\n        return c2;\n    }\n\n    // DSMath.wpow\n    function bpowi(uint a, uint n)\n        internal pure\n        returns (uint)\n    {\n        uint z = n % 2 != 0 ? a : BONE;\n\n        for (n /= 2; n != 0; n /= 2) {\n            a = bmul(a, a);\n\n            if (n % 2 != 0) {\n                z = bmul(z, a);\n            }\n        }\n        return z;\n    }\n\n    // Compute b^(e.w) by splitting it into (b^e)*(b^0.w).\n    // Use `bpowi` for `b^e` and `bpowK` for k iterations\n    // of approximation of b^0.w\n    function bpow(uint base, uint exp)\n        internal pure\n        returns (uint)\n    {\n        require(base \u003e= MIN_BPOW_BASE, \"ERR_BPOW_BASE_TOO_LOW\");\n        require(base \u003c= MAX_BPOW_BASE, \"ERR_BPOW_BASE_TOO_HIGH\");\n\n        uint whole  = bfloor(exp);   \n        uint remain = bsub(exp, whole);\n\n        uint wholePow = bpowi(base, btoi(whole));\n\n        if (remain == 0) {\n            return wholePow;\n        }\n\n        uint partialResult = bpowApprox(base, remain, BPOW_PRECISION);\n        return bmul(wholePow, partialResult);\n    }\n\n    function bpowApprox(uint base, uint exp, uint precision)\n        internal pure\n        returns (uint)\n    {\n        // term 0:\n        uint a     = exp;\n        (uint x, bool xneg)  = bsubSign(base, BONE);\n        uint term = BONE;\n        uint sum   = term;\n        bool negative = false;\n\n\n        // term(k) = numer / denom \n        //         = (product(a - i - 1, i=1--\u003ek) * x^k) / (k!)\n        // each iteration, multiply previous term by (a-(k-1)) * x / k\n        // continue until term is less than precision\n        for (uint i = 1; term \u003e= precision; i++) {\n            uint bigK = i * BONE;\n            (uint c, bool cneg) = bsubSign(a, bsub(bigK, BONE));\n            term = bmul(term, bmul(c, x));\n            term = bdiv(term, bigK);\n            if (term == 0) break;\n\n            if (xneg) negative = !negative;\n            if (cneg) negative = !negative;\n            if (negative) {\n                sum = bsub(sum, term);\n            } else {\n                sum = badd(sum, term);\n            }\n        }\n\n        return sum;\n    }\n\n}\n"},"BPool.sol":{"content":"// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see \u003chttp://www.gnu.org/licenses/\u003e.\n\npragma solidity 0.5.12;\n\nimport \"./BToken.sol\";\nimport \"./BMath.sol\";\n\ncontract BPool is BBronze, BToken, BMath {\n\n    struct Record {\n        bool bound;   // is token bound to pool\n        uint index;   // private\n        uint denorm;  // denormalized weight\n        uint balance;\n    }\n\n    event LOG_SWAP(\n        address indexed caller,\n        address indexed tokenIn,\n        address indexed tokenOut,\n        uint256         tokenAmountIn,\n        uint256         tokenAmountOut\n    );\n\n    event LOG_JOIN(\n        address indexed caller,\n        address indexed tokenIn,\n        uint256         tokenAmountIn\n    );\n\n    event LOG_EXIT(\n        address indexed caller,\n        address indexed tokenOut,\n        uint256         tokenAmountOut\n    );\n\n    event LOG_CALL(\n        bytes4  indexed sig,\n        address indexed caller,\n        bytes           data\n    ) anonymous;\n\n    modifier _logs_() {\n        emit LOG_CALL(msg.sig, msg.sender, msg.data);\n        _;\n    }\n\n    modifier _lock_() {\n        require(!_mutex, \"ERR_REENTRY\");\n        _mutex = true;\n        _;\n        _mutex = false;\n    }\n\n    modifier _viewlock_() {\n        require(!_mutex, \"ERR_REENTRY\");\n        _;\n    }\n\n    bool private _mutex;\n\n    address private _factory;    // BFactory address to push token exitFee to\n    address private _controller; // has CONTROL role\n    bool private _publicSwap; // true if PUBLIC can call SWAP functions\n\n    // `setSwapFee` and `finalize` require CONTROL\n    // `finalize` sets `PUBLIC can SWAP`, `PUBLIC can JOIN`\n    uint private _swapFee;\n    bool private _finalized;\n\n    address[] private _tokens;\n    mapping(address=\u003eRecord) private  _records;\n    uint private _totalWeight;\n\n    constructor() public {\n        _controller = msg.sender;\n        _factory = msg.sender;\n        _swapFee = MIN_FEE;\n        _publicSwap = false;\n        _finalized = false;\n    }\n\n    function isPublicSwap()\n        external view\n        returns (bool)\n    {\n        return _publicSwap;\n    }\n\n    function isFinalized()\n        external view\n        returns (bool)\n    {\n        return _finalized;\n    }\n\n    function isBound(address t)\n        external view\n        returns (bool)\n    {\n        return _records[t].bound;\n    }\n\n    function getNumTokens()\n        external view\n        returns (uint) \n    {\n        return _tokens.length;\n    }\n\n    function getCurrentTokens()\n        external view _viewlock_\n        returns (address[] memory tokens)\n    {\n        return _tokens;\n    }\n\n    function getFinalTokens()\n        external view\n        _viewlock_\n        returns (address[] memory tokens)\n    {\n        require(_finalized, \"ERR_NOT_FINALIZED\");\n        return _tokens;\n    }\n\n    function getDenormalizedWeight(address token)\n        external view\n        _viewlock_\n        returns (uint)\n    {\n\n        require(_records[token].bound, \"ERR_NOT_BOUND\");\n        return _records[token].denorm;\n    }\n\n    function getTotalDenormalizedWeight()\n        external view\n        _viewlock_\n        returns (uint)\n    {\n        return _totalWeight;\n    }\n\n    function getNormalizedWeight(address token)\n        external view\n        _viewlock_\n        returns (uint)\n    {\n\n        require(_records[token].bound, \"ERR_NOT_BOUND\");\n        uint denorm = _records[token].denorm;\n        return bdiv(denorm, _totalWeight);\n    }\n\n    function getBalance(address token)\n        external view\n        _viewlock_\n        returns (uint)\n    {\n\n        require(_records[token].bound, \"ERR_NOT_BOUND\");\n        return _records[token].balance;\n    }\n\n    function getSwapFee()\n        external view\n        _viewlock_\n        returns (uint)\n    {\n        return _swapFee;\n    }\n\n    function getController()\n        external view\n        _viewlock_\n        returns (address)\n    {\n        return _controller;\n    }\n\n    function setSwapFee(uint swapFee)\n        external\n        _logs_\n        _lock_\n    { \n        require(!_finalized, \"ERR_IS_FINALIZED\");\n        require(msg.sender == _controller, \"ERR_NOT_CONTROLLER\");\n        require(swapFee \u003e= MIN_FEE, \"ERR_MIN_FEE\");\n        require(swapFee \u003c= MAX_FEE, \"ERR_MAX_FEE\");\n        _swapFee = swapFee;\n    }\n\n    function setController(address manager)\n        external\n        _logs_\n        _lock_\n    {\n        require(msg.sender == _controller, \"ERR_NOT_CONTROLLER\");\n        _controller = manager;\n    }\n\n    function setPublicSwap(bool public_)\n        external\n        _logs_\n        _lock_\n    {\n        require(!_finalized, \"ERR_IS_FINALIZED\");\n        require(msg.sender == _controller, \"ERR_NOT_CONTROLLER\");\n        _publicSwap = public_;\n    }\n\n    function finalize()\n        external\n        _logs_\n        _lock_\n    {\n        require(msg.sender == _controller, \"ERR_NOT_CONTROLLER\");\n        require(!_finalized, \"ERR_IS_FINALIZED\");\n        require(_tokens.length \u003e= MIN_BOUND_TOKENS, \"ERR_MIN_TOKENS\");\n\n        _finalized = true;\n        _publicSwap = true;\n\n        _mintPoolShare(INIT_POOL_SUPPLY);\n        _pushPoolShare(msg.sender, INIT_POOL_SUPPLY);\n    }\n\n\n    function bind(address token, uint balance, uint denorm)\n        external\n        _logs_\n        // _lock_  Bind does not lock because it jumps to `rebind`, which does\n    {\n        require(msg.sender == _controller, \"ERR_NOT_CONTROLLER\");\n        require(!_records[token].bound, \"ERR_IS_BOUND\");\n        require(!_finalized, \"ERR_IS_FINALIZED\");\n\n        require(_tokens.length \u003c MAX_BOUND_TOKENS, \"ERR_MAX_TOKENS\");\n\n        _records[token] = Record({\n            bound: true,\n            index: _tokens.length,\n            denorm: 0,    // balance and denorm will be validated\n            balance: 0   // and set by `rebind`\n        });\n        _tokens.push(token);\n        rebind(token, balance, denorm);\n    }\n\n    function rebind(address token, uint balance, uint denorm)\n        public\n        _logs_\n        _lock_\n    {\n\n        require(msg.sender == _controller, \"ERR_NOT_CONTROLLER\");\n        require(_records[token].bound, \"ERR_NOT_BOUND\");\n        require(!_finalized, \"ERR_IS_FINALIZED\");\n\n        require(denorm \u003e= MIN_WEIGHT, \"ERR_MIN_WEIGHT\");\n        require(denorm \u003c= MAX_WEIGHT, \"ERR_MAX_WEIGHT\");\n        require(balance \u003e= MIN_BALANCE, \"ERR_MIN_BALANCE\");\n\n        // Adjust the denorm and totalWeight\n        uint oldWeight = _records[token].denorm;\n        if (denorm \u003e oldWeight) {\n            _totalWeight = badd(_totalWeight, bsub(denorm, oldWeight));\n            require(_totalWeight \u003c= MAX_TOTAL_WEIGHT, \"ERR_MAX_TOTAL_WEIGHT\");\n        } else if (denorm \u003c oldWeight) {\n            _totalWeight = bsub(_totalWeight, bsub(oldWeight, denorm));\n        }        \n        _records[token].denorm = denorm;\n\n        // Adjust the balance record and actual token balance\n        uint oldBalance = _records[token].balance;\n        _records[token].balance = balance;\n        if (balance \u003e oldBalance) {\n            _pullUnderlying(token, msg.sender, bsub(balance, oldBalance));\n        } else if (balance \u003c oldBalance) {\n            // In this case liquidity is being withdrawn, so charge EXIT_FEE\n            uint tokenBalanceWithdrawn = bsub(oldBalance, balance);\n            uint tokenExitFee = bmul(tokenBalanceWithdrawn, EXIT_FEE);\n            _pushUnderlying(token, msg.sender, bsub(tokenBalanceWithdrawn, tokenExitFee));\n            _pushUnderlying(token, _factory, tokenExitFee);\n        }\n    }\n\n    function unbind(address token)\n        external\n        _logs_\n        _lock_\n    {\n\n        require(msg.sender == _controller, \"ERR_NOT_CONTROLLER\");\n        require(_records[token].bound, \"ERR_NOT_BOUND\");\n        require(!_finalized, \"ERR_IS_FINALIZED\");\n\n        uint tokenBalance = _records[token].balance;\n        uint tokenExitFee = bmul(tokenBalance, EXIT_FEE);\n\n        _totalWeight = bsub(_totalWeight, _records[token].denorm);\n\n        // Swap the token-to-unbind with the last token,\n        // then delete the last token\n        uint index = _records[token].index;\n        uint last = _tokens.length - 1;\n        _tokens[index] = _tokens[last];\n        _records[_tokens[index]].index = index;\n        _tokens.pop();\n        _records[token] = Record({\n            bound: false,\n            index: 0,\n            denorm: 0,\n            balance: 0\n        });\n\n        _pushUnderlying(token, msg.sender, bsub(tokenBalance, tokenExitFee));\n        _pushUnderlying(token, _factory, tokenExitFee);\n    }\n\n    // Absorb any tokens that have been sent to this contract into the pool\n    function gulp(address token)\n        external\n        _logs_\n        _lock_\n    {\n        require(_records[token].bound, \"ERR_NOT_BOUND\");\n        _records[token].balance = IERC20(token).balanceOf(address(this));\n    }\n\n    function getSpotPrice(address tokenIn, address tokenOut)\n        external view\n        _viewlock_\n        returns (uint spotPrice)\n    {\n        require(_records[tokenIn].bound, \"ERR_NOT_BOUND\");\n        require(_records[tokenOut].bound, \"ERR_NOT_BOUND\");\n        Record storage inRecord = _records[tokenIn];\n        Record storage outRecord = _records[tokenOut];\n        return calcSpotPrice(inRecord.balance, inRecord.denorm, outRecord.balance, outRecord.denorm, _swapFee);\n    }\n\n    function getSpotPriceSansFee(address tokenIn, address tokenOut)\n        external view\n        _viewlock_\n        returns (uint spotPrice)\n    {\n        require(_records[tokenIn].bound, \"ERR_NOT_BOUND\");\n        require(_records[tokenOut].bound, \"ERR_NOT_BOUND\");\n        Record storage inRecord = _records[tokenIn];\n        Record storage outRecord = _records[tokenOut];\n        return calcSpotPrice(inRecord.balance, inRecord.denorm, outRecord.balance, outRecord.denorm, 0);\n    }\n\n    function joinPool(uint poolAmountOut, uint[] calldata maxAmountsIn)\n        external\n        _logs_\n        _lock_\n    {\n        require(_finalized, \"ERR_NOT_FINALIZED\");\n\n        uint poolTotal = totalSupply();\n        uint ratio = bdiv(poolAmountOut, poolTotal);\n        require(ratio != 0, \"ERR_MATH_APPROX\");\n\n        for (uint i = 0; i \u003c _tokens.length; i++) {\n            address t = _tokens[i];\n            uint bal = _records[t].balance;\n            uint tokenAmountIn = bmul(ratio, bal);\n            require(tokenAmountIn != 0, \"ERR_MATH_APPROX\");\n            require(tokenAmountIn \u003c= maxAmountsIn[i], \"ERR_LIMIT_IN\");\n            _records[t].balance = badd(_records[t].balance, tokenAmountIn);\n            emit LOG_JOIN(msg.sender, t, tokenAmountIn);\n            _pullUnderlying(t, msg.sender, tokenAmountIn);\n        }\n        _mintPoolShare(poolAmountOut);\n        _pushPoolShare(msg.sender, poolAmountOut);\n    }\n\n    function exitPool(uint poolAmountIn, uint[] calldata minAmountsOut)\n        external\n        _logs_\n        _lock_\n    {\n        require(_finalized, \"ERR_NOT_FINALIZED\");\n\n        uint poolTotal = totalSupply();\n        uint exitFee = bmul(poolAmountIn, EXIT_FEE);\n        uint pAiAfterExitFee = bsub(poolAmountIn, exitFee);\n        uint ratio = bdiv(pAiAfterExitFee, poolTotal);\n        require(ratio != 0, \"ERR_MATH_APPROX\");\n\n        _pullPoolShare(msg.sender, poolAmountIn);\n        _pushPoolShare(_factory, exitFee);\n        _burnPoolShare(pAiAfterExitFee);\n\n        for (uint i = 0; i \u003c _tokens.length; i++) {\n            address t = _tokens[i];\n            uint bal = _records[t].balance;\n            uint tokenAmountOut = bmul(ratio, bal);\n            require(tokenAmountOut != 0, \"ERR_MATH_APPROX\");\n            require(tokenAmountOut \u003e= minAmountsOut[i], \"ERR_LIMIT_OUT\");\n            _records[t].balance = bsub(_records[t].balance, tokenAmountOut);\n            emit LOG_EXIT(msg.sender, t, tokenAmountOut);\n            _pushUnderlying(t, msg.sender, tokenAmountOut);\n        }\n\n    }\n\n\n    function swapExactAmountIn(\n        address tokenIn,\n        uint tokenAmountIn,\n        address tokenOut,\n        uint minAmountOut,\n        uint maxPrice\n    )\n        external\n        _logs_\n        _lock_\n        returns (uint tokenAmountOut, uint spotPriceAfter)\n    {\n\n        require(_records[tokenIn].bound, \"ERR_NOT_BOUND\");\n        require(_records[tokenOut].bound, \"ERR_NOT_BOUND\");\n        require(_publicSwap, \"ERR_SWAP_NOT_PUBLIC\");\n\n        Record storage inRecord = _records[address(tokenIn)];\n        Record storage outRecord = _records[address(tokenOut)];\n\n        require(tokenAmountIn \u003c= bmul(inRecord.balance, MAX_IN_RATIO), \"ERR_MAX_IN_RATIO\");\n\n        uint spotPriceBefore = calcSpotPrice(\n                                    inRecord.balance,\n                                    inRecord.denorm,\n                                    outRecord.balance,\n                                    outRecord.denorm,\n                                    _swapFee\n                                );\n        require(spotPriceBefore \u003c= maxPrice, \"ERR_BAD_LIMIT_PRICE\");\n\n        tokenAmountOut = calcOutGivenIn(\n                            inRecord.balance,\n                            inRecord.denorm,\n                            outRecord.balance,\n                            outRecord.denorm,\n                            tokenAmountIn,\n                            _swapFee\n                        );\n        require(tokenAmountOut \u003e= minAmountOut, \"ERR_LIMIT_OUT\");\n\n        inRecord.balance = badd(inRecord.balance, tokenAmountIn);\n        outRecord.balance = bsub(outRecord.balance, tokenAmountOut);\n\n        spotPriceAfter = calcSpotPrice(\n                                inRecord.balance,\n                                inRecord.denorm,\n                                outRecord.balance,\n                                outRecord.denorm,\n                                _swapFee\n                            );\n        require(spotPriceAfter \u003e= spotPriceBefore, \"ERR_MATH_APPROX\");     \n        require(spotPriceAfter \u003c= maxPrice, \"ERR_LIMIT_PRICE\");\n        require(spotPriceBefore \u003c= bdiv(tokenAmountIn, tokenAmountOut), \"ERR_MATH_APPROX\");\n\n        emit LOG_SWAP(msg.sender, tokenIn, tokenOut, tokenAmountIn, tokenAmountOut);\n\n        _pullUnderlying(tokenIn, msg.sender, tokenAmountIn);\n        _pushUnderlying(tokenOut, msg.sender, tokenAmountOut);\n\n        return (tokenAmountOut, spotPriceAfter);\n    }\n\n    function swapExactAmountOut(\n        address tokenIn,\n        uint maxAmountIn,\n        address tokenOut,\n        uint tokenAmountOut,\n        uint maxPrice\n    )\n        external\n        _logs_\n        _lock_ \n        returns (uint tokenAmountIn, uint spotPriceAfter)\n    {\n        require(_records[tokenIn].bound, \"ERR_NOT_BOUND\");\n        require(_records[tokenOut].bound, \"ERR_NOT_BOUND\");\n        require(_publicSwap, \"ERR_SWAP_NOT_PUBLIC\");\n\n        Record storage inRecord = _records[address(tokenIn)];\n        Record storage outRecord = _records[address(tokenOut)];\n\n        require(tokenAmountOut \u003c= bmul(outRecord.balance, MAX_OUT_RATIO), \"ERR_MAX_OUT_RATIO\");\n\n        uint spotPriceBefore = calcSpotPrice(\n                                    inRecord.balance,\n                                    inRecord.denorm,\n                                    outRecord.balance,\n                                    outRecord.denorm,\n                                    _swapFee\n                                );\n        require(spotPriceBefore \u003c= maxPrice, \"ERR_BAD_LIMIT_PRICE\");\n\n        tokenAmountIn = calcInGivenOut(\n                            inRecord.balance,\n                            inRecord.denorm,\n                            outRecord.balance,\n                            outRecord.denorm,\n                            tokenAmountOut,\n                            _swapFee\n                        );\n        require(tokenAmountIn \u003c= maxAmountIn, \"ERR_LIMIT_IN\");\n\n        inRecord.balance = badd(inRecord.balance, tokenAmountIn);\n        outRecord.balance = bsub(outRecord.balance, tokenAmountOut);\n\n        spotPriceAfter = calcSpotPrice(\n                                inRecord.balance,\n                                inRecord.denorm,\n                                outRecord.balance,\n                                outRecord.denorm,\n                                _swapFee\n                            );\n        require(spotPriceAfter \u003e= spotPriceBefore, \"ERR_MATH_APPROX\");\n        require(spotPriceAfter \u003c= maxPrice, \"ERR_LIMIT_PRICE\");\n        require(spotPriceBefore \u003c= bdiv(tokenAmountIn, tokenAmountOut), \"ERR_MATH_APPROX\");\n\n        emit LOG_SWAP(msg.sender, tokenIn, tokenOut, tokenAmountIn, tokenAmountOut);\n\n        _pullUnderlying(tokenIn, msg.sender, tokenAmountIn);\n        _pushUnderlying(tokenOut, msg.sender, tokenAmountOut);\n\n        return (tokenAmountIn, spotPriceAfter);\n    }\n\n\n    function joinswapExternAmountIn(address tokenIn, uint tokenAmountIn, uint minPoolAmountOut)\n        external\n        _logs_\n        _lock_\n        returns (uint poolAmountOut)\n\n    {        \n        require(_finalized, \"ERR_NOT_FINALIZED\");\n        require(_records[tokenIn].bound, \"ERR_NOT_BOUND\");\n        require(tokenAmountIn \u003c= bmul(_records[tokenIn].balance, MAX_IN_RATIO), \"ERR_MAX_IN_RATIO\");\n\n        Record storage inRecord = _records[tokenIn];\n\n        poolAmountOut = calcPoolOutGivenSingleIn(\n                            inRecord.balance,\n                            inRecord.denorm,\n                            _totalSupply,\n                            _totalWeight,\n                            tokenAmountIn,\n                            _swapFee\n                        );\n\n        require(poolAmountOut \u003e= minPoolAmountOut, \"ERR_LIMIT_OUT\");\n\n        inRecord.balance = badd(inRecord.balance, tokenAmountIn);\n\n        emit LOG_JOIN(msg.sender, tokenIn, tokenAmountIn);\n\n        _mintPoolShare(poolAmountOut);\n        _pushPoolShare(msg.sender, poolAmountOut);\n        _pullUnderlying(tokenIn, msg.sender, tokenAmountIn);\n\n        return poolAmountOut;\n    }\n\n    function joinswapPoolAmountOut(address tokenIn, uint poolAmountOut, uint maxAmountIn)\n        external\n        _logs_\n        _lock_\n        returns (uint tokenAmountIn)\n    {\n        require(_finalized, \"ERR_NOT_FINALIZED\");\n        require(_records[tokenIn].bound, \"ERR_NOT_BOUND\");\n\n        Record storage inRecord = _records[tokenIn];\n\n        tokenAmountIn = calcSingleInGivenPoolOut(\n                            inRecord.balance,\n                            inRecord.denorm,\n                            _totalSupply,\n                            _totalWeight,\n                            poolAmountOut,\n                            _swapFee\n                        );\n\n        require(tokenAmountIn != 0, \"ERR_MATH_APPROX\");\n        require(tokenAmountIn \u003c= maxAmountIn, \"ERR_LIMIT_IN\");\n        \n        require(tokenAmountIn \u003c= bmul(_records[tokenIn].balance, MAX_IN_RATIO), \"ERR_MAX_IN_RATIO\");\n\n        inRecord.balance = badd(inRecord.balance, tokenAmountIn);\n\n        emit LOG_JOIN(msg.sender, tokenIn, tokenAmountIn);\n\n        _mintPoolShare(poolAmountOut);\n        _pushPoolShare(msg.sender, poolAmountOut);\n        _pullUnderlying(tokenIn, msg.sender, tokenAmountIn);\n\n        return tokenAmountIn;\n    }\n\n    function exitswapPoolAmountIn(address tokenOut, uint poolAmountIn, uint minAmountOut)\n        external\n        _logs_\n        _lock_\n        returns (uint tokenAmountOut)\n    {\n        require(_finalized, \"ERR_NOT_FINALIZED\");\n        require(_records[tokenOut].bound, \"ERR_NOT_BOUND\");\n\n        Record storage outRecord = _records[tokenOut];\n\n        tokenAmountOut = calcSingleOutGivenPoolIn(\n                            outRecord.balance,\n                            outRecord.denorm,\n                            _totalSupply,\n                            _totalWeight,\n                            poolAmountIn,\n                            _swapFee\n                        );\n\n        require(tokenAmountOut \u003e= minAmountOut, \"ERR_LIMIT_OUT\");\n        \n        require(tokenAmountOut \u003c= bmul(_records[tokenOut].balance, MAX_OUT_RATIO), \"ERR_MAX_OUT_RATIO\");\n\n        outRecord.balance = bsub(outRecord.balance, tokenAmountOut);\n\n        uint exitFee = bmul(poolAmountIn, EXIT_FEE);\n\n        emit LOG_EXIT(msg.sender, tokenOut, tokenAmountOut);\n\n        _pullPoolShare(msg.sender, poolAmountIn);\n        _burnPoolShare(bsub(poolAmountIn, exitFee));\n        _pushPoolShare(_factory, exitFee);\n        _pushUnderlying(tokenOut, msg.sender, tokenAmountOut);\n\n        return tokenAmountOut;\n    }\n\n    function exitswapExternAmountOut(address tokenOut, uint tokenAmountOut, uint maxPoolAmountIn)\n        external\n        _logs_\n        _lock_\n        returns (uint poolAmountIn)\n    {\n        require(_finalized, \"ERR_NOT_FINALIZED\");\n        require(_records[tokenOut].bound, \"ERR_NOT_BOUND\");\n        require(tokenAmountOut \u003c= bmul(_records[tokenOut].balance, MAX_OUT_RATIO), \"ERR_MAX_OUT_RATIO\");\n\n        Record storage outRecord = _records[tokenOut];\n\n        poolAmountIn = calcPoolInGivenSingleOut(\n                            outRecord.balance,\n                            outRecord.denorm,\n                            _totalSupply,\n                            _totalWeight,\n                            tokenAmountOut,\n                            _swapFee\n                        );\n\n        require(poolAmountIn != 0, \"ERR_MATH_APPROX\");\n        require(poolAmountIn \u003c= maxPoolAmountIn, \"ERR_LIMIT_IN\");\n\n        outRecord.balance = bsub(outRecord.balance, tokenAmountOut);\n\n        uint exitFee = bmul(poolAmountIn, EXIT_FEE);\n\n        emit LOG_EXIT(msg.sender, tokenOut, tokenAmountOut);\n\n        _pullPoolShare(msg.sender, poolAmountIn);\n        _burnPoolShare(bsub(poolAmountIn, exitFee));\n        _pushPoolShare(_factory, exitFee);\n        _pushUnderlying(tokenOut, msg.sender, tokenAmountOut);        \n\n        return poolAmountIn;\n    }\n\n\n    // ==\n    // \u0027Underlying\u0027 token-manipulation functions make external calls but are NOT locked\n    // You must `_lock_` or otherwise ensure reentry-safety\n\n    function _pullUnderlying(address erc20, address from, uint amount)\n        internal\n    {\n        bool xfer = IERC20(erc20).transferFrom(from, address(this), amount);\n        require(xfer, \"ERR_ERC20_FALSE\");\n    }\n\n    function _pushUnderlying(address erc20, address to, uint amount)\n        internal\n    {\n        bool xfer = IERC20(erc20).transfer(to, amount);\n        require(xfer, \"ERR_ERC20_FALSE\");\n    }\n\n    function _pullPoolShare(address from, uint amount)\n        internal\n    {\n        _pull(from, amount);\n    }\n\n    function _pushPoolShare(address to, uint amount)\n        internal\n    {\n        _push(to, amount);\n    }\n\n    function _mintPoolShare(uint amount)\n        internal\n    {\n        _mint(amount);\n    }\n\n    function _burnPoolShare(uint amount)\n        internal\n    {\n        _burn(amount);\n    }\n\n}\n"},"BToken.sol":{"content":"// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see \u003chttp://www.gnu.org/licenses/\u003e.\n\npragma solidity 0.5.12;\n\nimport \"./BNum.sol\";\n\n// Highly opinionated token implementation\n\ninterface IERC20 {\n    event Approval(address indexed src, address indexed dst, uint amt);\n    event Transfer(address indexed src, address indexed dst, uint amt);\n\n    function totalSupply() external view returns (uint);\n    function balanceOf(address whom) external view returns (uint);\n    function allowance(address src, address dst) external view returns (uint);\n\n    function approve(address dst, uint amt) external returns (bool);\n    function transfer(address dst, uint amt) external returns (bool);\n    function transferFrom(\n        address src, address dst, uint amt\n    ) external returns (bool);\n}\n\ncontract BTokenBase is BNum {\n\n    mapping(address =\u003e uint)                   internal _balance;\n    mapping(address =\u003e mapping(address=\u003euint)) internal _allowance;\n    uint internal _totalSupply;\n\n    event Approval(address indexed src, address indexed dst, uint amt);\n    event Transfer(address indexed src, address indexed dst, uint amt);\n\n    function _mint(uint amt) internal {\n        _balance[address(this)] = badd(_balance[address(this)], amt);\n        _totalSupply = badd(_totalSupply, amt);\n        emit Transfer(address(0), address(this), amt);\n    }\n\n    function _burn(uint amt) internal {\n        require(_balance[address(this)] \u003e= amt, \"ERR_INSUFFICIENT_BAL\");\n        _balance[address(this)] = bsub(_balance[address(this)], amt);\n        _totalSupply = bsub(_totalSupply, amt);\n        emit Transfer(address(this), address(0), amt);\n    }\n\n    function _move(address src, address dst, uint amt) internal {\n        require(_balance[src] \u003e= amt, \"ERR_INSUFFICIENT_BAL\");\n        _balance[src] = bsub(_balance[src], amt);\n        _balance[dst] = badd(_balance[dst], amt);\n        emit Transfer(src, dst, amt);\n    }\n\n    function _push(address to, uint amt) internal {\n        _move(address(this), to, amt);\n    }\n\n    function _pull(address from, uint amt) internal {\n        _move(from, address(this), amt);\n    }\n}\n\ncontract BToken is BTokenBase, IERC20 {\n\n    string  private _name     = \"Balancer Pool Token\";\n    string  private _symbol   = \"BPT\";\n    uint8   private _decimals = 18;\n\n    function name() public view returns (string memory) {\n        return _name;\n    }\n\n    function symbol() public view returns (string memory) {\n        return _symbol;\n    }\n\n    function decimals() public view returns(uint8) {\n        return _decimals;\n    }\n\n    function allowance(address src, address dst) external view returns (uint) {\n        return _allowance[src][dst];\n    }\n\n    function balanceOf(address whom) external view returns (uint) {\n        return _balance[whom];\n    }\n\n    function totalSupply() public view returns (uint) {\n        return _totalSupply;\n    }\n\n    function approve(address dst, uint amt) external returns (bool) {\n        _allowance[msg.sender][dst] = amt;\n        emit Approval(msg.sender, dst, amt);\n        return true;\n    }\n\n    function increaseApproval(address dst, uint amt) external returns (bool) {\n        _allowance[msg.sender][dst] = badd(_allowance[msg.sender][dst], amt);\n        emit Approval(msg.sender, dst, _allowance[msg.sender][dst]);\n        return true;\n    }\n\n    function decreaseApproval(address dst, uint amt) external returns (bool) {\n        uint oldValue = _allowance[msg.sender][dst];\n        if (amt \u003e oldValue) {\n            _allowance[msg.sender][dst] = 0;\n        } else {\n            _allowance[msg.sender][dst] = bsub(oldValue, amt);\n        }\n        emit Approval(msg.sender, dst, _allowance[msg.sender][dst]);\n        return true;\n    }\n\n    function transfer(address dst, uint amt) external returns (bool) {\n        _move(msg.sender, dst, amt);\n        return true;\n    }\n\n    function transferFrom(address src, address dst, uint amt) external returns (bool) {\n        require(msg.sender == src || amt \u003c= _allowance[src][msg.sender], \"ERR_BTOKEN_BAD_CALLER\");\n        _move(src, dst, amt);\n        if (msg.sender != src \u0026\u0026 _allowance[src][msg.sender] != uint256(-1)) {\n            _allowance[src][msg.sender] = bsub(_allowance[src][msg.sender], amt);\n            emit Approval(msg.sender, dst, _allowance[src][msg.sender]);\n        }\n        return true;\n    }\n}\n"}}

    File 3 of 3: SAFE
    /**
     *Submitted for verification at Etherscan.io on 2020-07-31
    */
    
    pragma solidity ^0.5.16;
    
    interface IERC20 {
        function totalSupply() external view returns (uint);
        function balanceOf(address account) external view returns (uint);
        function transfer(address recipient, uint amount) external returns (bool);
        function allowance(address owner, address spender) external view returns (uint);
        function approve(address spender, uint amount) external returns (bool);
        function transferFrom(address sender, address recipient, uint amount) external returns (bool);
        event Transfer(address indexed from, address indexed to, uint value);
        event Approval(address indexed owner, address indexed spender, uint value);
    }
    
    contract Context {
        constructor () internal { }
        // solhint-disable-previous-line no-empty-blocks
    
        function _msgSender() internal view returns (address payable) {
            return msg.sender;
        }
    }
    
    contract ERC20 is Context, IERC20 {
        using SafeMath for uint;
    
        mapping (address => uint) private _balances;
    
        mapping (address => mapping (address => uint)) private _allowances;
    
        uint private _totalSupply;
        function totalSupply() public view returns (uint) {
            return _totalSupply;
        }
        function balanceOf(address account) public view returns (uint) {
            return _balances[account];
        }
        function transfer(address recipient, uint amount) public returns (bool) {
            _transfer(_msgSender(), recipient, amount);
            return true;
        }
        function allowance(address owner, address spender) public view returns (uint) {
            return _allowances[owner][spender];
        }
        function approve(address spender, uint amount) public returns (bool) {
            _approve(_msgSender(), spender, amount);
            return true;
        }
        function transferFrom(address sender, address recipient, uint amount) public returns (bool) {
            _transfer(sender, recipient, amount);
            _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
            return true;
        }
        function increaseAllowance(address spender, uint addedValue) public returns (bool) {
            _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
            return true;
        }
        function decreaseAllowance(address spender, uint subtractedValue) public returns (bool) {
            _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
            return true;
        }
        function _transfer(address sender, address recipient, uint amount) internal {
            require(sender != address(0), "ERC20: transfer from the zero address");
            require(recipient != address(0), "ERC20: transfer to the zero address");
    
            _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, uint amount) internal {
            require(account != address(0), "ERC20: mint to the zero address");
    
            _totalSupply = _totalSupply.add(amount);
            _balances[account] = _balances[account].add(amount);
            emit Transfer(address(0), account, amount);
        }
        function _burn(address account, uint amount) internal {
            require(account != address(0), "ERC20: burn from the zero address");
    
            _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, uint amount) internal {
            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);
        }
    }
    
    contract ERC20Detailed is IERC20 {
        string private _name;
        string private _symbol;
        uint8 private _decimals;
    
        constructor (string memory name, string memory symbol, uint8 decimals) public {
            _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;
        }
    }
    
    library SafeMath {
        function add(uint a, uint b) internal pure returns (uint) {
            uint c = a + b;
            require(c >= a, "SafeMath: addition overflow");
    
            return c;
        }
        function sub(uint a, uint b) internal pure returns (uint) {
            return sub(a, b, "SafeMath: subtraction overflow");
        }
        function sub(uint a, uint b, string memory errorMessage) internal pure returns (uint) {
            require(b <= a, errorMessage);
            uint c = a - b;
    
            return c;
        }
        function mul(uint a, uint b) internal pure returns (uint) {
            if (a == 0) {
                return 0;
            }
    
            uint c = a * b;
            require(c / a == b, "SafeMath: multiplication overflow");
    
            return c;
        }
        function div(uint a, uint b) internal pure returns (uint) {
            return div(a, b, "SafeMath: division by zero");
        }
        function div(uint a, uint b, string memory errorMessage) internal pure returns (uint) {
            // Solidity only automatically asserts when dividing by 0
            require(b > 0, errorMessage);
            uint c = a / b;
    
            return c;
        }
    }
    
    library Address {
        function isContract(address account) internal view returns (bool) {
            bytes32 codehash;
            bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
            // solhint-disable-next-line no-inline-assembly
            assembly { codehash := extcodehash(account) }
            return (codehash != 0x0 && codehash != accountHash);
        }
    }
    
    library SafeERC20 {
        using SafeMath for uint;
        using Address for address;
    
        function safeTransfer(IERC20 token, address to, uint value) internal {
            callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
        }
    
        function safeTransferFrom(IERC20 token, address from, address to, uint value) internal {
            callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
        }
    
        function safeApprove(IERC20 token, address spender, uint 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 callOptionalReturn(IERC20 token, bytes memory data) private {
            require(address(token).isContract(), "SafeERC20: call to non-contract");
    
            // solhint-disable-next-line avoid-low-level-calls
            (bool success, bytes memory returndata) = address(token).call(data);
            require(success, "SafeERC20: low-level call failed");
    
            if (returndata.length > 0) { // Return data is optional
                // solhint-disable-next-line max-line-length
                require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
            }
        }
    }
    
    contract SAFE is ERC20, ERC20Detailed {
      using SafeERC20 for IERC20;
      using Address for address;
      using SafeMath for uint;
      
      
      address public governance;
      mapping (address => bool) public minters;
    
      constructor () public ERC20Detailed("yieldfarming.insure", "SAFE", 18) {
          governance = tx.origin;
      }
    
      function mint(address account, uint256 amount) public {
          require(minters[msg.sender], "!minter");
          _mint(account, amount);
      }
      
      function setGovernance(address _governance) public {
          require(msg.sender == governance, "!governance");
          governance = _governance;
      }
      
      function addMinter(address _minter) public {
          require(msg.sender == governance, "!governance");
          minters[_minter] = true;
      }
      
      function removeMinter(address _minter) public {
          require(msg.sender == governance, "!governance");
          minters[_minter] = false;
      }
    }