/**
* Source Code first verified at https://etherscan.io on Monday, April 15, 2019
(UTC) */
// File: @gnosis.pm/util-contracts/contracts/Math.sol
pragma solidity ^0.5.2;
/// @title Math library - Allows calculation of logarithmic and exponential functions
/// @author Alan Lu - <[email protected]>
/// @author Stefan George - <[email protected]>
library GnosisMath {
/*
* Constants
*/
// This is equal to 1 in our calculations
uint public constant ONE = 0x10000000000000000;
uint public constant LN2 = 0xb17217f7d1cf79ac;
uint public constant LOG2_E = 0x171547652b82fe177;
/*
* Public functions
*/
/// @dev Returns natural exponential function value of given x
/// @param x x
/// @return e**x
function exp(int x) public pure returns (uint) {
// revert if x is > MAX_POWER, where
// MAX_POWER = int(mp.floor(mp.log(mpf(2**256 - 1) / ONE) * ONE))
require(x <= 2454971259878909886679);
// return 0 if exp(x) is tiny, using
// MIN_POWER = int(mp.floor(mp.log(mpf(1) / ONE) * ONE))
if (x < -818323753292969962227) return 0;
// Transform so that e^x -> 2^x
x = x * int(ONE) / int(LN2);
// 2^x = 2^whole(x) * 2^frac(x)
// ^^^^^^^^^^ is a bit shift
// so Taylor expand on z = frac(x)
int shift;
uint z;
if (x >= 0) {
shift = x / int(ONE);
z = uint(x % int(ONE));
} else {
shift = x / int(ONE) - 1;
z = ONE - uint(-x % int(ONE));
}
// 2^x = 1 + (ln 2) x + (ln 2)^2/2! x^2 + ...
//
// Can generate the z coefficients using mpmath and the following lines
// >>> from mpmath import mp
// >>> mp.dps = 100
// >>> ONE = 0x10000000000000000
// >>> print('\n'.join(hex(int(mp.log(2)**i / mp.factorial(i) * ONE)) for i in range(1, 7)))
// 0xb17217f7d1cf79ab
// 0x3d7f7bff058b1d50
// 0xe35846b82505fc5
// 0x276556df749cee5
// 0x5761ff9e299cc4
// 0xa184897c363c3
uint zpow = z;
uint result = ONE;
result += 0xb17217f7d1cf79ab * zpow / ONE;
zpow = zpow * z / ONE;
result += 0x3d7f7bff058b1d50 * zpow / ONE;
zpow = zpow * z / ONE;
result += 0xe35846b82505fc5 * zpow / ONE;
zpow = zpow * z / ONE;
result += 0x276556df749cee5 * zpow / ONE;
zpow = zpow * z / ONE;
result += 0x5761ff9e299cc4 * zpow / ONE;
zpow = zpow * z / ONE;
result += 0xa184897c363c3 * zpow / ONE;
zpow = zpow * z / ONE;
result += 0xffe5fe2c4586 * zpow / ONE;
zpow = zpow * z / ONE;
result += 0x162c0223a5c8 * zpow / ONE;
zpow = zpow * z / ONE;
result += 0x1b5253d395e * zpow / ONE;
zpow = zpow * z / ONE;
result += 0x1e4cf5158b * zpow / ONE;
zpow = zpow * z / ONE;
result += 0x1e8cac735 * zpow / ONE;
zpow = zpow * z / ONE;
result += 0x1c3bd650 * zpow / ONE;
zpow = zpow * z / ONE;
result += 0x1816193 * zpow / ONE;
zpow = zpow * z / ONE;
result += 0x131496 * zpow / ONE;
zpow = zpow * z / ONE;
result += 0xe1b7 * zpow / ONE;
zpow = zpow * z / ONE;
result += 0x9c7 * zpow / ONE;
if (shift >= 0) {
if (result >> (256 - shift) > 0) return (2 ** 256 - 1);
return result << shift;
} else return result >> (-shift);
}
/// @dev Returns natural logarithm value of given x
/// @param x x
/// @return ln(x)
function ln(uint x) public pure returns (int) {
require(x > 0);
// binary search for floor(log2(x))
int ilog2 = floorLog2(x);
int z;
if (ilog2 < 0) z = int(x << uint(-ilog2));
else z = int(x >> uint(ilog2));
// z = x * 2^-⌊log₂x⌋
// so 1 <= z < 2
// and ln z = ln x - ⌊log₂x⌋/log₂e
// so just compute ln z using artanh series
// and calculate ln x from that
int term = (z - int(ONE)) * int(ONE) / (z + int(ONE));
int halflnz = term;
int termpow = term * term / int(ONE) * term / int(ONE);
halflnz += termpow / 3;
termpow = termpow * term / int(ONE) * term / int(ONE);
halflnz += termpow / 5;
termpow = termpow * term / int(ONE) * term / int(ONE);
halflnz += termpow / 7;
termpow = termpow * term / int(ONE) * term / int(ONE);
halflnz += termpow / 9;
termpow = termpow * term / int(ONE) * term / int(ONE);
halflnz += termpow / 11;
termpow = termpow * term / int(ONE) * term / int(ONE);
halflnz += termpow / 13;
termpow = termpow * term / int(ONE) * term / int(ONE);
halflnz += termpow / 15;
termpow = termpow * term / int(ONE) * term / int(ONE);
halflnz += termpow / 17;
termpow = termpow * term / int(ONE) * term / int(ONE);
halflnz += termpow / 19;
termpow = termpow * term / int(ONE) * term / int(ONE);
halflnz += termpow / 21;
termpow = termpow * term / int(ONE) * term / int(ONE);
halflnz += termpow / 23;
termpow = termpow * term / int(ONE) * term / int(ONE);
halflnz += termpow / 25;
return (ilog2 * int(ONE)) * int(ONE) / int(LOG2_E) + 2 * halflnz;
}
/// @dev Returns base 2 logarithm value of given x
/// @param x x
/// @return logarithmic value
function floorLog2(uint x) public pure returns (int lo) {
lo = -64;
int hi = 193;
// I use a shift here instead of / 2 because it floors instead of rounding towards 0
int mid = (hi + lo) >> 1;
while ((lo + 1) < hi) {
if (mid < 0 && x << uint(-mid) < ONE || mid >= 0 && x >> uint(mid) < ONE) hi = mid;
else lo = mid;
mid = (hi + lo) >> 1;
}
}
/// @dev Returns maximum of an array
/// @param nums Numbers to look through
/// @return Maximum number
function max(int[] memory nums) public pure returns (int maxNum) {
require(nums.length > 0);
maxNum = -2 ** 255;
for (uint i = 0; i < nums.length; i++) if (nums[i] > maxNum) maxNum = nums[i];
}
/// @dev Returns whether an add operation causes an overflow
/// @param a First addend
/// @param b Second addend
/// @return Did no overflow occur?
function safeToAdd(uint a, uint b) internal pure returns (bool) {
return a + b >= a;
}
/// @dev Returns whether a subtraction operation causes an underflow
/// @param a Minuend
/// @param b Subtrahend
/// @return Did no underflow occur?
function safeToSub(uint a, uint b) internal pure returns (bool) {
return a >= b;
}
/// @dev Returns whether a multiply operation causes an overflow
/// @param a First factor
/// @param b Second factor
/// @return Did no overflow occur?
function safeToMul(uint a, uint b) internal pure returns (bool) {
return b == 0 || a * b / b == a;
}
/// @dev Returns sum if no overflow occurred
/// @param a First addend
/// @param b Second addend
/// @return Sum
function add(uint a, uint b) internal pure returns (uint) {
require(safeToAdd(a, b));
return a + b;
}
/// @dev Returns difference if no overflow occurred
/// @param a Minuend
/// @param b Subtrahend
/// @return Difference
function sub(uint a, uint b) internal pure returns (uint) {
require(safeToSub(a, b));
return a - b;
}
/// @dev Returns product if no overflow occurred
/// @param a First factor
/// @param b Second factor
/// @return Product
function mul(uint a, uint b) internal pure returns (uint) {
require(safeToMul(a, b));
return a * b;
}
/// @dev Returns whether an add operation causes an overflow
/// @param a First addend
/// @param b Second addend
/// @return Did no overflow occur?
function safeToAdd(int a, int b) internal pure returns (bool) {
return (b >= 0 && a + b >= a) || (b < 0 && a + b < a);
}
/// @dev Returns whether a subtraction operation causes an underflow
/// @param a Minuend
/// @param b Subtrahend
/// @return Did no underflow occur?
function safeToSub(int a, int b) internal pure returns (bool) {
return (b >= 0 && a - b <= a) || (b < 0 && a - b > a);
}
/// @dev Returns whether a multiply operation causes an overflow
/// @param a First factor
/// @param b Second factor
/// @return Did no overflow occur?
function safeToMul(int a, int b) internal pure returns (bool) {
return (b == 0) || (a * b / b == a);
}
/// @dev Returns sum if no overflow occurred
/// @param a First addend
/// @param b Second addend
/// @return Sum
function add(int a, int b) internal pure returns (int) {
require(safeToAdd(a, b));
return a + b;
}
/// @dev Returns difference if no overflow occurred
/// @param a Minuend
/// @param b Subtrahend
/// @return Difference
function sub(int a, int b) internal pure returns (int) {
require(safeToSub(a, b));
return a - b;
}
/// @dev Returns product if no overflow occurred
/// @param a First factor
/// @param b Second factor
/// @return Product
function mul(int a, int b) internal pure returns (int) {
require(safeToMul(a, b));
return a * b;
}
}
// File: @gnosis.pm/util-contracts/contracts/Token.sol
/// Implements ERC 20 Token standard: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
pragma solidity ^0.5.2;
/// @title Abstract token contract - Functions to be implemented by token contracts
contract Token {
/*
* Events
*/
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
/*
* Public functions
*/
function transfer(address to, uint value) public returns (bool);
function transferFrom(address from, address to, uint value) public returns (bool);
function approve(address spender, uint value) public returns (bool);
function balanceOf(address owner) public view returns (uint);
function allowance(address owner, address spender) public view returns (uint);
function totalSupply() public view returns (uint);
}
// File: @gnosis.pm/util-contracts/contracts/Proxy.sol
pragma solidity ^0.5.2;
/// @title Proxied - indicates that a contract will be proxied. Also defines storage requirements for Proxy.
/// @author Alan Lu - <[email protected]>
contract Proxied {
address public masterCopy;
}
/// @title Proxy - Generic proxy contract allows to execute all transactions applying the code of a master contract.
/// @author Stefan George - <[email protected]>
contract Proxy is Proxied {
/// @dev Constructor function sets address of master copy contract.
/// @param _masterCopy Master copy address.
constructor(address _masterCopy) public {
require(_masterCopy != address(0), "The master copy is required");
masterCopy = _masterCopy;
}
/// @dev Fallback function forwards all transactions and returns all received return data.
function() external payable {
address _masterCopy = masterCopy;
assembly {
calldatacopy(0, 0, calldatasize)
let success := delegatecall(not(0), _masterCopy, 0, calldatasize, 0, 0)
returndatacopy(0, 0, returndatasize)
switch success
case 0 {
revert(0, returndatasize)
}
default {
return(0, returndatasize)
}
}
}
}
// File: @gnosis.pm/util-contracts/contracts/GnosisStandardToken.sol
pragma solidity ^0.5.2;
/**
* Deprecated: Use Open Zeppeling one instead
*/
contract StandardTokenData {
/*
* Storage
*/
mapping(address => uint) balances;
mapping(address => mapping(address => uint)) allowances;
uint totalTokens;
}
/**
* Deprecated: Use Open Zeppeling one instead
*/
/// @title Standard token contract with overflow protection
contract GnosisStandardToken is Token, StandardTokenData {
using GnosisMath for *;
/*
* Public functions
*/
/// @dev Transfers sender's tokens to a given address. Returns success
/// @param to Address of token receiver
/// @param value Number of tokens to transfer
/// @return Was transfer successful?
function transfer(address to, uint value) public returns (bool) {
if (!balances[msg.sender].safeToSub(value) || !balances[to].safeToAdd(value)) {
return false;
}
balances[msg.sender] -= value;
balances[to] += value;
emit Transfer(msg.sender, to, value);
return true;
}
/// @dev Allows allowed third party to transfer tokens from one address to another. Returns success
/// @param from Address from where tokens are withdrawn
/// @param to Address to where tokens are sent
/// @param value Number of tokens to transfer
/// @return Was transfer successful?
function transferFrom(address from, address to, uint value) public returns (bool) {
if (!balances[from].safeToSub(value) || !allowances[from][msg.sender].safeToSub(
value
) || !balances[to].safeToAdd(value)) {
return false;
}
balances[from] -= value;
allowances[from][msg.sender] -= value;
balances[to] += value;
emit Transfer(from, to, value);
return true;
}
/// @dev Sets approved amount of tokens for spender. Returns success
/// @param spender Address of allowed account
/// @param value Number of approved tokens
/// @return Was approval successful?
function approve(address spender, uint value) public returns (bool) {
allowances[msg.sender][spender] = value;
emit Approval(msg.sender, spender, value);
return true;
}
/// @dev Returns number of allowed tokens for given address
/// @param owner Address of token owner
/// @param spender Address of token spender
/// @return Remaining allowance for spender
function allowance(address owner, address spender) public view returns (uint) {
return allowances[owner][spender];
}
/// @dev Returns number of tokens owned by given address
/// @param owner Address of token owner
/// @return Balance of owner
function balanceOf(address owner) public view returns (uint) {
return balances[owner];
}
/// @dev Returns total supply of tokens
/// @return Total supply
function totalSupply() public view returns (uint) {
return totalTokens;
}
}
// File: contracts/TokenOWL.sol
pragma solidity ^0.5.2;
contract TokenOWL is Proxied, GnosisStandardToken {
using GnosisMath for *;
string public constant name = "OWL Token";
string public constant symbol = "OWL";
uint8 public constant decimals = 18;
struct masterCopyCountdownType {
address masterCopy;
uint timeWhenAvailable;
}
masterCopyCountdownType masterCopyCountdown;
address public creator;
address public minter;
event Minted(address indexed to, uint256 amount);
event Burnt(address indexed from, address indexed user, uint256 amount);
modifier onlyCreator() {
// R1
require(msg.sender == creator, "Only the creator can perform the transaction");
_;
}
/// @dev trickers the update process via the proxyMaster for a new address _masterCopy
/// updating is only possible after 30 days
function startMasterCopyCountdown(address _masterCopy) public onlyCreator {
require(address(_masterCopy) != address(0), "The master copy must be a valid address");
// Update masterCopyCountdown
masterCopyCountdown.masterCopy = _masterCopy;
masterCopyCountdown.timeWhenAvailable = now + 30 days;
}
/// @dev executes the update process via the proxyMaster for a new address _masterCopy
function updateMasterCopy() public onlyCreator {
require(address(masterCopyCountdown.masterCopy) != address(0), "The master copy must be a valid address");
require(
block.timestamp >= masterCopyCountdown.timeWhenAvailable,
"It's not possible to update the master copy during the waiting period"
);
// Update masterCopy
masterCopy = masterCopyCountdown.masterCopy;
}
function getMasterCopy() public view returns (address) {
return masterCopy;
}
/// @dev Set minter. Only the creator of this contract can call this.
/// @param newMinter The new address authorized to mint this token
function setMinter(address newMinter) public onlyCreator {
minter = newMinter;
}
/// @dev change owner/creator of the contract. Only the creator/owner of this contract can call this.
/// @param newOwner The new address, which should become the owner
function setNewOwner(address newOwner) public onlyCreator {
creator = newOwner;
}
/// @dev Mints OWL.
/// @param to Address to which the minted token will be given
/// @param amount Amount of OWL to be minted
function mintOWL(address to, uint amount) public {
require(minter != address(0), "The minter must be initialized");
require(msg.sender == minter, "Only the minter can mint OWL");
balances[to] = balances[to].add(amount);
totalTokens = totalTokens.add(amount);
emit Minted(to, amount);
emit Transfer(address(0), to, amount);
}
/// @dev Burns OWL.
/// @param user Address of OWL owner
/// @param amount Amount of OWL to be burnt
function burnOWL(address user, uint amount) public {
allowances[user][msg.sender] = allowances[user][msg.sender].sub(amount);
balances[user] = balances[user].sub(amount);
totalTokens = totalTokens.sub(amount);
emit Burnt(msg.sender, user, amount);
emit Transfer(user, address(0), amount);
}
function getMasterCopyCountdown() public view returns (address, uint) {
return (masterCopyCountdown.masterCopy, masterCopyCountdown.timeWhenAvailable);
}
}