// SPDX-License-Identifier: MIT
// ----------------------------------------------------------------------------
// yBXTB Utility Token
//
// Symbol : yBXTB
// Name : Yield Token BXTB
// Initial supply: 100,000,000.000000
// Decimals : 6
// ----------------------------------------------------------------------------
pragma solidity ^0.7.4;
// ----------------------------------------------------------------------------
// Safe maths
// ----------------------------------------------------------------------------
library SafeMath {
function addSafe(uint _a, uint _b) internal pure returns (uint c) {
c = _a + _b;
require(c >= _a);
}
function subSafe(uint _a, uint _b) internal pure returns (uint c) {
require(_b <= _a, "Insufficient balance");
c = _a - _b;
}
function mulSafe(uint _a, uint _b) internal pure returns (uint c) {
c = _a * _b;
require(_a == 0 || c / _a == _b);
}
function divSafe(uint _a, uint _b) internal pure returns (uint c) {
require(_b > 0);
c = _a / _b;
}
}
// ----------------------------------------------------------------------------
// ERC Token Standard #20 Interface
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
// ----------------------------------------------------------------------------
interface ERC20Interface {
function totalSupply() external view returns (uint);
function balanceOf(address _tokenOwner) external view returns (uint);
function allowance(address _tokenOwner, address _spender) external view returns (uint);
function transfer(address _to, uint _amount) external returns (bool);
function approve(address _spender, uint _amount) external returns (bool);
function transferFrom(address _from, address _to, uint _amount) external returns (bool);
event Transfer(address indexed _from, address indexed _to, uint _tokens);
event Approval(address indexed _tokenOwner, address indexed _spender, uint _tokens);
}
// ----------------------------------------------------------------------------
// Contract function to receive approval and execute function in one call
// ----------------------------------------------------------------------------
interface ApproveAndCallFallBack {
function receiveApproval(address _tokenOwner, uint256 _amount, address _token, bytes memory _data) external;
}
interface SettlementInterface {
function disburseCommissions(bool _disburseBackstop) external;
}
// ----------------------------------------------------------------------------
// Owned contract
// ----------------------------------------------------------------------------
contract Owned {
address public owner;
address public newOwner;
constructor() {
owner = msg.sender;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
event OwnershipTransferred(address indexed _from, address indexed _to);
function transferOwnership(address _newOwner) public onlyOwner {
newOwner = _newOwner;
}
function acceptOwnership() public {
require(msg.sender == newOwner);
owner = newOwner;
newOwner = address(0);
emit OwnershipTransferred(owner, newOwner);
}
}
// ----------------------------------------------------------------------------
// ERC20 Token, with the addition of symbol, name and decimals and a
// fixed supply
// ----------------------------------------------------------------------------
contract yBXTBToken is ERC20Interface, Owned {
using SafeMath for uint;
string public constant symbol = "yBXTB";
string public constant name = "Yield Token for BXTB";
uint public constant decimals = 6;
uint totalSupplyAmount;
mapping(address => uint) public balances;
mapping(address => mapping(address => uint)) public allowed;
uint public pausedForSettlementBlock;
address public settlementAdmin;
address public serviceContractAddress;
bool public pausedForSettlement;
constructor() {
totalSupplyAmount = 100000000 * 10**uint(decimals);
emit Mint(totalSupplyAmount);
balances[owner] = totalSupplyAmount;
emit Transfer(address(0), owner, totalSupplyAmount);
}
// Fix for the ERC20 short address attack
modifier onlyPayloadSize(uint _size) {
require(msg.data.length == _size + 4, "Input length error");
_;
}
modifier pauseCheck {
if(pausedForSettlement == true) {
// Auto release lock after 10 blocks to prevent deadlock
if(block.number.subSafe(pausedForSettlementBlock) >= 10) pausedForSettlement = false;
else revert("Paused for settlement");
}
_;
}
// When new coins are minted after contract creation
event Mint(uint _amount);
// ----------------------------------------------------------------------------
// Standard ERC20 implementations
// ----------------------------------------------------------------------------
// Read
function totalSupply() public override view returns (uint) {
return totalSupplyAmount.subSafe(balances[address(0)]);
}
function balanceOf(address _tokenOwner) public override view returns (uint) {
return balances[_tokenOwner];
}
function allowance(address _tokenOwner, address _spender) public override view returns (uint) {
return allowed[_tokenOwner][_spender];
}
// Write
function transfer(address _to, uint _amount) public override onlyPayloadSize(2 * 32) pauseCheck returns (bool) {
require(_to != address(this), "Can not transfer to this");
if(serviceContractAddress != address(0)) require(_to != serviceContractAddress, "Address not allowed");
balances[msg.sender] = balances[msg.sender].subSafe(_amount);
balances[_to] = balances[_to].addSafe(_amount);
emit Transfer(msg.sender, _to, _amount);
return true;
}
function approve(address _spender, uint _amount) public override onlyPayloadSize(2 * 32) pauseCheck returns (bool) {
require(_amount <= balances[msg.sender], "Insufficient balance");
// To change the approve amount you first have to reduce the`
// allowance to zero by calling `approve(_spender, 0)` if it is not
// already 0 to mitigate the race condition described here:
// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
if(_amount > 0) require(allowed[msg.sender][_spender] == 0, "Zero allowance first");
allowed[msg.sender][_spender] = _amount;
emit Approval(msg.sender, _spender, _amount);
return true;
}
function transferFrom(address _tokenOwner, address _to, uint _amount) public override onlyPayloadSize(3 * 32) pauseCheck returns (bool) {
require(_to != address(this), "Can not transfer to this");
allowed[_tokenOwner][msg.sender] = allowed[_tokenOwner][msg.sender].subSafe(_amount);
balances[_tokenOwner] = balances[_tokenOwner].subSafe(_amount);
balances[_to] = balances[_to].addSafe(_amount);
emit Transfer(_tokenOwner, _to, _amount);
return true;
}
// ----------------------------------------------------------------------------
// Other admin, common and courtesy functions
// ----------------------------------------------------------------------------
function approveAndCall(address _spender, uint _amount, bytes memory _data) pauseCheck public returns (bool) {
// Prevent ERC20 short address attack
// _data length is not fixed. These bytes are packed into 32 byte chunks
uint length256;
if(_data.length > 0) {
length256 = _data.length / 32;
if(32 * length256 < _data.length) length256++;
}
require(msg.data.length == (((4 + length256) * 32) + 4), "Input length error");
require(_amount <= balances[msg.sender], "Insufficient balance");
// To change the approve amount you first have to reduce the`
// allowance to zero by calling `approve(_spender, 0)` if it is not
// already 0 to mitigate the race condition described here:
// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
if(_amount > 0) require(allowed[msg.sender][_spender] == 0, "Zero allowance first");
allowed[msg.sender][_spender] = _amount;
emit Approval(msg.sender, _spender, _amount);
ApproveAndCallFallBack(_spender).receiveApproval(msg.sender, _amount, address(this), _data);
return true;
}
function mint(uint _newTokens) public onlyOwner pauseCheck {
totalSupplyAmount = totalSupplyAmount.addSafe(_newTokens);
emit Mint(totalSupplyAmount);
balances[owner] = balances[owner].addSafe(_newTokens);
emit Transfer(address(0), owner, _newTokens);
}
function totalOutstanding() public view returns (uint) {
// Outstanding token = total supply - contract owner - burned
uint outOfCirculation;
if(owner == address(0)) outOfCirculation = balances[address(0)];
else outOfCirculation = balances[address(0)].addSafe(balances[owner]);
return totalSupplyAmount.subSafe(outOfCirculation);
}
function setServiceContractAddress(address _setAddress) public onlyOwner onlyPayloadSize(1 * 32) {
// Prevent lost coins in companion service contract when user accidentally calls transfer()
serviceContractAddress = _setAddress;
}
function performSettlement(bool _doPause, bool _doDisburseCommission, bool _doDisburseBackstop) external {
require((msg.sender == settlementAdmin) || (msg.sender == owner), "Caller not authorized");
// Disable or enable transfer(), transferFrom(), etc. functions
pausedForSettlement = _doPause;
if(_doPause == true) pausedForSettlementBlock = block.number;
if(_doDisburseCommission == true) {
// Call service contract to disburse commissions and backstop balances
require(serviceContractAddress != address(0), "Service Contract not set");
SettlementInterface(serviceContractAddress).disburseCommissions(_doDisburseBackstop);
}
}
// Change Settlement Admin for daily settlements
function changeSettlementAdmin(address _newAddress) external {
require(msg.data.length == 32 + 4, "Address error"); // Prevent input error
require((msg.sender == settlementAdmin) || (msg.sender == owner), "Caller not authorized");
settlementAdmin = _newAddress;
}
// Retrieve any ERC20 tokens accidentally sent to this contract for owner
function transferAnyERC20Token(address _fromTokenContract, uint _amount) public onlyOwner returns (bool success) {
return ERC20Interface(_fromTokenContract).transfer(owner, _amount);
}
}
{
"compilationTarget": {
"yBXTBToken.sol": "yBXTBToken"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_tokenOwner","type":"address"},{"indexed":true,"internalType":"address","name":"_spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"_tokens","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"}],"name":"OwnershipTransferred","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":"_tokens","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenOwner","type":"address"},{"internalType":"address","name":"_spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"approveAndCall","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenOwner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newAddress","type":"address"}],"name":"changeSettlementAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newTokens","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"newOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pausedForSettlement","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pausedForSettlementBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_doPause","type":"bool"},{"internalType":"bool","name":"_doDisburseCommission","type":"bool"},{"internalType":"bool","name":"_doDisburseBackstop","type":"bool"}],"name":"performSettlement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"serviceContractAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_setAddress","type":"address"}],"name":"setServiceContractAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settlementAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalOutstanding","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_fromTokenContract","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transferAnyERC20Token","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenOwner","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]