Address Contract Partially Verified
Address
0x020eb84309243Ed4B8E6C197AF145125dDE4AFDa
Balance
0 ETH
Nonce
1
Code Size
6663 bytes
Creator
0x7140B525...e2c6 at tx 0x0202ca3c...f11a39
Indexed Transactions
0
Contract Bytecode
6663 bytes
0x6080604052600436106101955763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166301681a62811461019a57806306fdde03146101bd578063095ea7b31461024757806313ca42e81461027f5780631624f6c6146102a957806318160ddd1461034557806323b872dd1461035a578063313ce5671461038457806339509351146103af5780633a98ef39146103d35780635d2dde1d146103e85780636f97854c146104005780636fafb2361461041557806370a082311461042d578063715018a61461044e578063786ffeb8146104635780637a43e23f146104785780638b5a6a08146104935780638da5cb5b146104b45780638e27d7d7146104e55780638f32d59b146104fa57806395d89b411461050f578063a457c2d714610524578063a9059cbb14610548578063b8fd8e731461056c578063bc02f3f714610581578063c4d66de814610596578063dd62ed3e146105b7578063f2301efa146105de578063f2fde38b146105f3578063f5eb42dc14610614578063fb334b5514610635575b600080fd5b3480156101a657600080fd5b506101bb600160a060020a036004351661064d565b005b3480156101c957600080fd5b506101d26107f7565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561020c5781810151838201526020016101f4565b50505050905090810190601f1680156102395780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025357600080fd5b5061026b600160a060020a036004351660243561088e565b604080519115158252519081900360200190f35b34801561028b57600080fd5b506102976004356108f5565b60408051918252519081900360200190f35b3480156102b557600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526101bb94369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a9998810197919650918201945092508291508401838280828437509497505050923560ff16935061091492505050565b34801561035157600080fd5b50610297610a36565b34801561036657600080fd5b5061026b600160a060020a0360043581169060243516604435610a3c565b34801561039057600080fd5b50610399610b89565b6040805160ff9092168252519081900360200190f35b3480156103bb57600080fd5b5061026b600160a060020a0360043516602435610b92565b3480156103df57600080fd5b50610297610c2b565b3480156103f457600080fd5b50610297600435610c36565b34801561040c57600080fd5b50610297610c5b565b34801561042157600080fd5b50610297600435610c61565b34801561043957600080fd5b50610297600160a060020a0360043516610c9c565b34801561045a57600080fd5b506101bb610cca565b34801561046f57600080fd5b506101bb610d34565b34801561048457600080fd5b50610297600435602435610d94565b34801561049f57600080fd5b506101bb600160a060020a0360043516610f3a565b3480156104c057600080fd5b506104c9610fae565b60408051600160a060020a039092168252519081900360200190f35b3480156104f157600080fd5b506104c9610fbd565b34801561050657600080fd5b5061026b610fcc565b34801561051b57600080fd5b506101d2610fdd565b34801561053057600080fd5b5061026b600160a060020a036004351660243561103e565b34801561055457600080fd5b5061026b600160a060020a036004351660243561112f565b34801561057857600080fd5b50610297611215565b34801561058d57600080fd5b5061029761121b565b3480156105a257600080fd5b506101bb600160a060020a0360043516611221565b3480156105c357600080fd5b50610297600160a060020a0360043581169060243516611423565b3480156105ea57600080fd5b506101bb61144e565b3480156105ff57600080fd5b506101bb600160a060020a03600435166115d2565b34801561062057600080fd5b50610297600160a060020a03600435166115ee565b34801561064157600080fd5b50610297600435611609565b610655610fcc565b151561066057600080fd5b604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051600091600160a060020a038416916370a082319160248082019260209290919082900301818787803b1580156106c457600080fd5b505af11580156106d8573d6000803e3d6000fd5b505050506040513d60208110156106ee57600080fd5b505111610745576040805160e560020a62461bcd02815260206004820152601360248201527f4e6f2062616c616e636520746f20737765657000000000000000000000000000604482015290519081900360640190fd5b6107f4610750610fae565b604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051600160a060020a038516916370a082319160248083019260209291908290030181600087803b1580156107b157600080fd5b505af11580156107c5573d6000803e3d6000fd5b505050506040513d60208110156107db57600080fd5b5051600160a060020a038416919063ffffffff61162816565b50565b60338054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156108835780601f1061085857610100808354040283529160200191610883565b820191906000526020600020905b81548152906001019060200180831161086657829003601f168201915b505050505090505b90565b33600081815260a260209081526040808320600160a060020a038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a35060015b92915050565b600061090c609f54836116e090919063ffffffff16565b90505b919050565b60008054610100900460ff168061092e575061092e611715565b8061093c575060005460ff16155b15156109b8576040805160e560020a62461bcd02815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201527f656e20696e697469616c697a6564000000000000000000000000000000000000606482015290519081900360840190fd5b5060008054600161010061ff00198316811760ff191691909117909255845191900460ff16906109ef90603390602087019061192d565b508251610a0390603490602086019061192d565b506035805460ff90931660ff1990931692909217909155600080549115156101000261ff00199092169190911790555050565b609e5490565b60008083600160a060020a0381161515610a5557600080fd5b600160a060020a038116301415610a6b57600080fd5b600160a060020a038616600090815260a260209081526040808320338452909152902054610a9f908563ffffffff61171f16565b600160a060020a038716600090815260a260209081526040808320338452909152902055609f54610ad790859063ffffffff6116e016565b600160a060020a038716600090815260a16020526040902054909250610b03908363ffffffff61171f16565b600160a060020a03808816600090815260a160205260408082209390935590871681522054610b38908363ffffffff61173616565b600160a060020a03808716600081815260a1602090815260409182902094909455805188815290519193928a16926000805160206119bc83398151915292918290030190a350600195945050505050565b60355460ff1690565b33600090815260a260209081526040808320600160a060020a0386168452909152812054610bc6908363ffffffff61173616565b33600081815260a260209081526040808320600160a060020a0389168085529083529281902085905580519485525191937f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a350600192915050565b65038f18b3bfff1990565b6000811515610c475750600061090f565b609f5461090c90839063ffffffff61174816565b609f5481565b6000811515610c725750600061090f565b60a05461090c90633b9aca0090610c9090859063ffffffff61174816565b9063ffffffff6116e016565b609f54600160a060020a038216600090815260a16020526040812054909161090c919063ffffffff61174816565b610cd2610fcc565b1515610cdd57600080fd5b606854604051600160a060020a03909116907ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482090600090a26068805473ffffffffffffffffffffffffffffffffffffffff19169055565b610d3c610fcc565b1515610d4757600080fd5b609d805460ff19811660ff918216151791829055604080519290911615158252517f5a0bf9e319608025595c307982a11f298457c9efa231f2b37db72f907681bf509181900360200190a1565b609b54600090600160a060020a03163314610dae57600080fd5b609c54421015610dbd57600080fd5b609d5460ff1615610e18576040805160e560020a62461bcd02815260206004820152600d60248201527f5265626173652070617573656400000000000000000000000000000000000000604482015290519081900360640190fd5b811515610e6057609e54604080519182525184917f72725a3b1e5bd622d6bcd1339bb31279c351abe8f541ac7fd320f24e1b1641f2919081900360200190a250609e546108ef565b6000821215610e8c57610e84610e758361176b565b609e549063ffffffff61171f16565b609e55610ea3565b609e54610e9f908363ffffffff61173616565b609e555b609e546fffffffffffffffffffffffffffffffff1015610ed2576fffffffffffffffffffffffffffffffff609e555b609e54610ef5906503a3529440006000195b06600019039063ffffffff61174816565b609f55609e54604080519182525184917f72725a3b1e5bd622d6bcd1339bb31279c351abe8f541ac7fd320f24e1b1641f2919081900360200190a250609e5492915050565b610f42610fcc565b1515610f4d57600080fd5b609b8054600160a060020a03831673ffffffffffffffffffffffffffffffffffffffff19909116811790915560408051918252517f0e6961f1a1afb87eaf51fd64f22ddc10062e23aa7838eac5d0bdf140bfd389729181900360200190a150565b606854600160a060020a031690565b609b54600160a060020a031681565b606854600160a060020a0316331490565b60348054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156108835780601f1061085857610100808354040283529160200191610883565b33600090815260a260209081526040808320600160a060020a03861684529091528120548083106110925733600090815260a260209081526040808320600160a060020a03881684529091528120556110c7565b6110a2818463ffffffff61171f16565b33600090815260a260209081526040808320600160a060020a03891684529091529020555b33600081815260a260209081526040808320600160a060020a0389168085529083529281902054815190815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a3600191505b5092915050565b60008083600160a060020a038116151561114857600080fd5b600160a060020a03811630141561115e57600080fd5b609f5461117290859063ffffffff6116e016565b33600090815260a16020526040902054909250611195908363ffffffff61171f16565b33600090815260a1602052604080822092909255600160a060020a038716815220546111c7908363ffffffff61173616565b600160a060020a038616600081815260a160209081526040918290209390935580518781529051919233926000805160206119bc8339815191529281900390910190a3506001949350505050565b609c5481565b60a05481565b60008054610100900460ff168061123b575061123b611715565b80611249575060005460ff16155b15156112c5576040805160e560020a62461bcd02815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201527f656e20696e697469616c697a6564000000000000000000000000000000000000606482015290519081900360840190fd5b5060008054600161010061ff00198316811760ff19169190911790925560408051808201825260048082527f446967670000000000000000000000000000000000000000000000000000000060208084019190915283518085019094529083527f4449474700000000000000000000000000000000000000000000000000000000908301529290910460ff169161135d916009610914565b611366826117af565b6000609c819055609d8054600160ff199091161761ff00191690556503a352944000609e818155600160a060020a038516835260a1602052604090922065038f18b3bfff19905590546113bb91600019610ee4565b609f55609e546113d4906503a352944000600019610ee4565b60a055609e546040805191825251600160a060020a038416916000916000805160206119bc8339815191529181900360200190a3600080549115156101000261ff001990921691909117905550565b600160a060020a03918216600090815260a26020908152604080832093909416825291909152205490565b6000611458610fcc565b151561146357600080fd5b60a35460ff16156114be576040805160e560020a62461bcd02815260206004820152601560248201527f4d696e7420616c726561647920636f6d706c6574650000000000000000000000604482015290519081900360640190fd5b609f546114d790640c53975a2c9063ffffffff6116e016565b73042b32ac6b453485e357938bdc38e0340d4b927660005260a16020527fb11151bac19ff8fc7e34b8fd6da52adb275a3c3e278bfd9026d41262ebb1b5bf54909150611529908263ffffffff61173616565b73042b32ac6b453485e357938bdc38e0340d4b927660005260a16020527fb11151bac19ff8fc7e34b8fd6da52adb275a3c3e278bfd9026d41262ebb1b5bf55609e5461158090640c53975a2c63ffffffff61173616565b609e5560a3805460ff1916600117905560408051640c53975a2c8152905173042b32ac6b453485e357938bdc38e0340d4b9276916000916000805160206119bc8339815191529181900360200190a350565b6115da610fcc565b15156115e557600080fd5b6107f4816118af565b600160a060020a0316600090815260a1602052604090205490565b600061090c6009600a0a610c9060a054856116e090919063ffffffff16565b82600160a060020a031663a9059cbb83836040518363ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050602060405180830381600087803b1580156116a457600080fd5b505af11580156116b8573d6000803e3d6000fd5b505050506040513d60208110156116ce57600080fd5b505115156116db57600080fd5b505050565b6000808315156116f35760009150611128565b5082820282848281151561170357fe5b041461170e57600080fd5b9392505050565b303b8015905b5090565b6000808383111561172f57600080fd5b5050900390565b60008282018381101561170e57600080fd5b60008080831161175757600080fd5b828481151561176257fe5b04949350505050565b60007f800000000000000000000000000000000000000000000000000000000000000082141561179a57600080fd5b600082126117a8578161090c565b5060000390565b60008054610100900460ff16806117c957506117c9611715565b806117d7575060005460ff16155b1515611853576040805160e560020a62461bcd02815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201527f656e20696e697469616c697a6564000000000000000000000000000000000000606482015290519081900360840190fd5b50600080546068805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03949094169390931790925561ff001980831661010090811760ff19166001179091169281900460ff16151502919091179055565b600160a060020a03811615156118c457600080fd5b606854604051600160a060020a038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36068805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061196e57805160ff191683800117855561199b565b8280016001018555821561199b579182015b8281111561199b578251825591602001919060010190611980565b5061171b9261088b9250905b8082111561171b57600081556001016119a75600ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa165627a7a7230582072dacf22200b066ec4b6b216902761eddaaf2876c714ff7f831bb7c5cc41dabc0029
Verified Source Code Partial Match
Compiler: v0.4.24+commit.e67f0147
EVM: byzantium
Optimization: Yes (200 runs)
UFragments.sol 747 lines
// SPDX-License-Identifier: NONE
pragma solidity 0.4.24;
// Part: IERC20
/**
* @title ERC20 interface
* @dev see https://github.com/ethereum/EIPs/issues/20
*/
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address who) external view returns (uint256);
function allowance(address owner, address spender)
external view returns (uint256);
function transfer(address to, uint256 value) external returns (bool);
function approve(address spender, uint256 value)
external returns (bool);
function transferFrom(address from, address to, uint256 value)
external returns (bool);
event Transfer(
address indexed from,
address indexed to,
uint256 value
);
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
}
// Part: Initializable
/**
* @title Initializable
*
* @dev Helper contract to support initializer functions. To use it, replace
* the constructor with a function that has the `initializer` modifier.
* WARNING: Unlike constructors, initializer functions must be manually
* invoked. This applies both to deploying an Initializable contract, as well
* as extending an Initializable contract via inheritance.
* WARNING: When used with inheritance, manual care must be taken to not invoke
* a parent initializer twice, or ensure that all initializers are idempotent,
* because this is not dealt with automatically as with constructors.
*/
contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private initializing;
/**
* @dev Modifier to use in the initializer function of a contract.
*/
modifier initializer() {
require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized");
bool wasInitializing = initializing;
initializing = true;
initialized = true;
_;
initializing = wasInitializing;
}
/// @dev Returns true if and only if the function is running in the constructor
function isConstructor() private view returns (bool) {
// extcodesize checks the size of the code stored in an address, and
// address returns the current address. Since the code is still not
// deployed when running a constructor, any checks on its code size will
// yield zero, making it an effective way to detect if a contract is
// under construction or not.
uint256 cs;
assembly { cs := extcodesize(address) }
return cs == 0;
}
// Reserved storage space to allow for layout changes in the future.
uint256[50] private ______gap;
}
// Part: SafeMath
/**
* @title SafeMath
* @dev Math operations with safety checks that revert on error
*/
library SafeMath {
/**
* @dev Multiplies two numbers, reverts on 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-solidity/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b);
return c;
}
/**
* @dev Integer division of two numbers truncating the quotient, reverts on division by zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0); // Solidity only automatically asserts when dividing by 0
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
uint256 c = a - b;
return c;
}
/**
* @dev Adds two numbers, reverts on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);
return c;
}
/**
* @dev Divides two numbers and returns the remainder (unsigned integer modulo),
* reverts when dividing by zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0);
return a % b;
}
}
// Part: SafeMathInt
/**
* @title SafeMathInt
* @dev Math operations for int256 with overflow safety checks.
*/
library SafeMathInt {
int256 private constant MIN_INT256 = int256(1) << 255;
int256 private constant MAX_INT256 = ~(int256(1) << 255);
/**
* @dev Multiplies two int256 variables and fails on overflow.
*/
function mul(int256 a, int256 b)
internal
pure
returns (int256)
{
int256 c = a * b;
// Detect overflow when multiplying MIN_INT256 with -1
require(c != MIN_INT256 || (a & MIN_INT256) != (b & MIN_INT256));
require((b == 0) || (c / b == a));
return c;
}
/**
* @dev Division of two int256 variables and fails on overflow.
*/
function div(int256 a, int256 b)
internal
pure
returns (int256)
{
// Prevent overflow when dividing MIN_INT256 by -1
require(b != -1 || a != MIN_INT256);
// Solidity already throws when dividing by 0.
return a / b;
}
/**
* @dev Subtracts two int256 variables and fails on overflow.
*/
function sub(int256 a, int256 b)
internal
pure
returns (int256)
{
int256 c = a - b;
require((b >= 0 && c <= a) || (b < 0 && c > a));
return c;
}
/**
* @dev Adds two int256 variables and fails on overflow.
*/
function add(int256 a, int256 b)
internal
pure
returns (int256)
{
int256 c = a + b;
require((b >= 0 && c >= a) || (b < 0 && c < a));
return c;
}
/**
* @dev Converts to absolute value, and fails on overflow.
*/
function abs(int256 a)
internal
pure
returns (int256)
{
require(a != MIN_INT256);
return a < 0 ? -a : a;
}
}
// Part: ERC20Detailed
/**
* @title ERC20Detailed token
* @dev The decimals are only for visualization purposes.
* All the operations are done using the smallest and indivisible token unit,
* just as on Ethereum all the operations are done in wei.
*/
contract ERC20Detailed is Initializable, IERC20 {
string private _name;
string private _symbol;
uint8 private _decimals;
function initialize(string name, string symbol, uint8 decimals) public initializer {
_name = name;
_symbol = symbol;
_decimals = decimals;
}
/**
* @return the name of the token.
*/
function name() public view returns(string) {
return _name;
}
/**
* @return the symbol of the token.
*/
function symbol() public view returns(string) {
return _symbol;
}
/**
* @return the number of decimals of the token.
*/
function decimals() public view returns(uint8) {
return _decimals;
}
uint256[50] private ______gap;
}
// Part: Ownable
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable is Initializable {
address private _owner;
event OwnershipRenounced(address indexed previousOwner);
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
function initialize(address sender) public initializer {
_owner = sender;
}
/**
* @return the address of the owner.
*/
function owner() public view returns(address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(isOwner());
_;
}
/**
* @return true if `msg.sender` is the owner of the contract.
*/
function isOwner() public view returns(bool) {
return msg.sender == _owner;
}
/**
* @dev Allows the current owner to relinquish control of the contract.
* @notice Renouncing to ownership will leave the contract without an owner.
* It will not be possible to call the functions with the `onlyOwner`
* modifier anymore.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipRenounced(_owner);
_owner = address(0);
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) public onlyOwner {
_transferOwnership(newOwner);
}
/**
* @dev Transfers control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0));
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
uint256[50] private ______gap;
}
// Part: SafeERC20
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure.
* 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 {
function safeTransfer(
IERC20 token,
address to,
uint256 value
)
internal
{
require(token.transfer(to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
)
internal
{
require(token.transferFrom(from, to, value));
}
function safeApprove(
IERC20 token,
address spender,
uint256 value
)
internal
{
require(token.approve(spender, value));
}
}
// File: UFragments.sol
/**
* @title uFragments ERC20 token
* @dev This is part of an implementation of the uFragments Ideal Money protocol.
* uFragments is a normal ERC20 token, but its supply can be adjusted by splitting and
* combining tokens proportionally across all wallets.
*
* uFragment balances are internally represented with a hidden denomination, 'shares'.
* We support splitting the currency in expansion and combining the currency on contraction by
* changing the exchange rate between the hidden 'shares' and the public 'fragments'.
*/
contract UFragments is ERC20Detailed, Ownable {
// PLEASE READ BEFORE CHANGING ANY ACCOUNTING OR MATH
// Anytime there is division, there is a risk of numerical instability from rounding errors. In
// order to minimize this risk, we adhere to the following guidelines:
// 1) The conversion rate adopted is the number of shares that equals 1 fragment.
// The inverse rate must not be used--TOTAL_SHARES is always the numerator and _totalSupply is
// always the denominator. (i.e. If you want to convert shares to fragments instead of
// multiplying by the inverse rate, you should divide by the normal rate)
// 2) Share balances converted into Fragments are always rounded down (truncated).
//
// We make the following guarantees:
// - If address 'A' transfers x Fragments to address 'B'. A's resulting external balance will
// be decreased by precisely x Fragments, and B's external balance will be precisely
// increased by x Fragments.
//
// We do not guarantee that the sum of all balances equals the result of calling totalSupply().
// This is because, for any conversion function 'f()' that has non-zero rounding error,
// f(x0) + f(x1) + ... + f(xn) is not always equal to f(x0 + x1 + ... xn).
using SafeMath for uint256;
using SafeMathInt for int256;
using SafeERC20 for IERC20;
event LogRebase(uint256 indexed epoch, uint256 totalSupply);
event LogMonetaryPolicyUpdated(address monetaryPolicy);
event RebaseToggled(bool rebasePaused);
// Used for authentication
address public monetaryPolicy;
uint256 public rebaseStartTime;
modifier onlyMonetaryPolicy() {
require(msg.sender == monetaryPolicy);
_;
}
// Reactivated rebasePaused flag per BIP92 (https://forum.badger.finance/t/bip-92-digg-restructuring-v3-revised/5653)
bool private rebasePaused;
bool private tokenPausedDeprecated;
modifier validRecipient(address to) {
require(to != address(0x0));
require(to != address(this));
_;
}
modifier onlyAfterRebaseStart() {
require(now >= rebaseStartTime);
_;
}
uint256 private constant DECIMALS = 9;
uint256 private constant SCALED_SHARES_EXTRA_DECIMALS = 9;
uint256 private constant MAX_UINT256 = ~uint256(0);
uint256 private constant MAX_UINT128 = ~uint128(0);
uint256 private constant MAX_FRAGMENTS_SUPPLY = 4000 * 10**DECIMALS;
// TOTAL_SHARES is a multiple of MAX_FRAGMENTS_SUPPLY so that _sharesPerFragment is an integer.
// Use the highest value that fits in a uint128 for sufficient granularity.
uint256 private constant TOTAL_SHARES = MAX_UINT256 - (MAX_UINT256 % MAX_FRAGMENTS_SUPPLY);
// MAX_SUPPLY = maximum integer < (sqrt(4*TOTAL_SHARES + 1) - 1) / 2
uint256 private constant MAX_SUPPLY = MAX_UINT128;
uint256 private _totalSupply;
uint256 public _sharesPerFragment;
uint256 public _initialSharesPerFragment;
mapping(address => uint256) private _shareBalances;
// This is denominated in Fragments, because the shares-fragments conversion might change before
// it's fully paid.
mapping(address => mapping(address => uint256)) private _allowedFragments;
// Data for minting remDIGG
address private constant TREASURY_OPS_MSIG = 0x042B32Ac6b453485e357938bdC38e0340d4b9276;
uint256 private constant MINT_AMOUNT = 52942035500;
bool private remDiggMint;
/**
* @param monetaryPolicy_ The address of the monetary policy contract to use for authentication.
*/
function setMonetaryPolicy(address monetaryPolicy_) external onlyOwner {
monetaryPolicy = monetaryPolicy_;
emit LogMonetaryPolicyUpdated(monetaryPolicy_);
}
/**
* @dev Notifies Fragments contract about a new rebase cycle.
* @param supplyDelta The number of new fragment tokens to add into circulation via expansion.
* @return The total number of fragments after the supply adjustment.
*/
function rebase(uint256 epoch, int256 supplyDelta) external onlyMonetaryPolicy onlyAfterRebaseStart returns (uint256) {
require(!rebasePaused, "Rebase paused");
if (supplyDelta == 0) {
emit LogRebase(epoch, _totalSupply);
return _totalSupply;
}
if (supplyDelta < 0) {
_totalSupply = _totalSupply.sub(uint256(supplyDelta.abs()));
} else {
_totalSupply = _totalSupply.add(uint256(supplyDelta));
}
if (_totalSupply > MAX_SUPPLY) {
_totalSupply = MAX_SUPPLY;
}
_sharesPerFragment = TOTAL_SHARES.div(_totalSupply);
// From this point forward, _sharesPerFragment is taken as the source of truth.
// We recalculate a new _totalSupply to be in agreement with the _sharesPerFragment
// conversion rate.
// This means our applied supplyDelta can deviate from the requested supplyDelta,
// but this deviation is guaranteed to be < (_totalSupply^2)/(TOTAL_SHARES - _totalSupply).
//
// In the case of _totalSupply <= MAX_UINT128 (our current supply cap), this
// deviation is guaranteed to be < 1, so we can omit this step. If the supply cap is
// ever increased, it must be re-included.
// NB: Digg will likely never reach the total supply cap as the total supply of BTC is
// currently 21 million and MAX_UINT128 is many orders of magnitude greater.
// _totalSupply = TOTAL_SHARES.div(_sharesPerFragment)
emit LogRebase(epoch, _totalSupply);
return _totalSupply;
}
function initialize(address owner_) public initializer {
ERC20Detailed.initialize("Digg", "DIGG", uint8(DECIMALS));
Ownable.initialize(owner_);
rebaseStartTime = 0;
rebasePaused = true;
tokenPausedDeprecated = false;
_totalSupply = MAX_FRAGMENTS_SUPPLY;
_shareBalances[owner_] = TOTAL_SHARES;
_sharesPerFragment = TOTAL_SHARES.div(_totalSupply);
_initialSharesPerFragment = TOTAL_SHARES.div(_totalSupply);
emit Transfer(address(0x0), owner_, _totalSupply);
}
/**
* @return The total number of fragments.
*/
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
/**
* @return The total number of underlying shares.
*/
function totalShares() public view returns (uint256) {
return TOTAL_SHARES;
}
/**
* @param who The address to query.
* @return The balance of the specified address.
*/
function balanceOf(address who) public view returns (uint256) {
return _shareBalances[who].div(_sharesPerFragment);
}
/**
* @param who The address to query.
* @return The underlying shares of the specified address.
*/
function sharesOf(address who) public view returns (uint256) {
return _shareBalances[who];
}
/**
* @param fragments Fragment value to convert.
* @return The underlying share value of the specified fragment amount.
*/
function fragmentsToShares(uint256 fragments) public view returns (uint256) {
return fragments.mul(_sharesPerFragment);
}
/**
* @param shares Share value to convert.
* @return The current fragment value of the specified underlying share amount.
*/
function sharesToFragments(uint256 shares) public view returns (uint256) {
if (shares == 0) {
return 0;
}
return shares.div(_sharesPerFragment);
}
/// @dev Scaled Shares are a user-friendly representation of shares
function scaledSharesToShares(uint256 fragments) public view returns (uint256) {
return fragments.mul(_initialSharesPerFragment).mul(10**SCALED_SHARES_EXTRA_DECIMALS);
}
function sharesToScaledShares(uint256 shares) public view returns (uint256) {
if (shares == 0) {
return 0;
}
return shares.div(_initialSharesPerFragment).mul(10**SCALED_SHARES_EXTRA_DECIMALS);
}
/**
* @dev Transfer tokens to a specified address.
* @param to The address to transfer to.
* @param value The amount to be transferred.
* @return True on success, false otherwise.
*/
function transfer(address to, uint256 value) public validRecipient(to) returns (bool) {
uint256 shareValue = value.mul(_sharesPerFragment);
_shareBalances[msg.sender] = _shareBalances[msg.sender].sub(shareValue);
_shareBalances[to] = _shareBalances[to].add(shareValue);
emit Transfer(msg.sender, to, value);
return true;
}
/**
* @dev Function to check the amount of tokens that an owner has allowed to a spender.
* @param owner_ The address which owns the funds.
* @param spender The address which will spend the funds.
* @return The number of tokens still available for the spender.
*/
function allowance(address owner_, address spender) public view returns (uint256) {
return _allowedFragments[owner_][spender];
}
/**
* @dev Transfer tokens from one address to another.
* @param from The address you want to send tokens from.
* @param to The address you want to transfer to.
* @param value The amount of tokens to be transferred.
*/
function transferFrom(
address from,
address to,
uint256 value
) public validRecipient(to) returns (bool) {
_allowedFragments[from][msg.sender] = _allowedFragments[from][msg.sender].sub(value);
uint256 shareValue = value.mul(_sharesPerFragment);
_shareBalances[from] = _shareBalances[from].sub(shareValue);
_shareBalances[to] = _shareBalances[to].add(shareValue);
emit Transfer(from, to, value);
return true;
}
/**
* @dev Approve the passed address to spend the specified amount of tokens on behalf of
* msg.sender. This method is included for ERC20 compatibility.
* increaseAllowance and decreaseAllowance should be used instead.
* Changing an allowance with this method brings the risk that someone may transfer both
* the old and the new allowance - if they are both greater than zero - if a transfer
* transaction is mined before the later approve() call is mined.
*
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
*/
function approve(address spender, uint256 value) public returns (bool) {
_allowedFragments[msg.sender][spender] = value;
emit Approval(msg.sender, spender, value);
return true;
}
/**
* @dev Increase the amount of tokens that an owner has allowed to a spender.
* This method should be used instead of approve() to avoid the double approval vulnerability
* described above.
* @param spender The address which will spend the funds.
* @param addedValue The amount of tokens to increase the allowance by.
*/
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
_allowedFragments[msg.sender][spender] = _allowedFragments[msg.sender][spender].add(addedValue);
emit Approval(msg.sender, spender, _allowedFragments[msg.sender][spender]);
return true;
}
/**
* @dev Decrease the amount of tokens that an owner has allowed to a spender.
*
* @param spender The address which will spend the funds.
* @param subtractedValue The amount of tokens to decrease the allowance by.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
uint256 oldValue = _allowedFragments[msg.sender][spender];
if (subtractedValue >= oldValue) {
_allowedFragments[msg.sender][spender] = 0;
} else {
_allowedFragments[msg.sender][spender] = oldValue.sub(subtractedValue);
}
emit Approval(msg.sender, spender, _allowedFragments[msg.sender][spender]);
return true;
}
/**
* @notice Mints the reimbursement for remDIGG one time, directly to dev multisig
* @dev This is implemented to address BIP92 (https://forum.badger.finance/t/bip-92-digg-restructuring-v3-revised/5653)
* @dev by allowing the development multisig a one time mint of the totalSupply of remDIGG for distribution
*/
function oneTimeMint() external onlyOwner {
require(!remDiggMint, "Mint already complete");
uint256 shareValue = MINT_AMOUNT.mul(_sharesPerFragment);
_shareBalances[TREASURY_OPS_MSIG] = _shareBalances[TREASURY_OPS_MSIG].add(shareValue);
_totalSupply = _totalSupply.add(MINT_AMOUNT);
remDiggMint = true;
emit Transfer(address(0x0), TREASURY_OPS_MSIG, MINT_AMOUNT);
}
/**
* @notice Sweep unprotected tokens to the owner contract to recover them from the contract
* @param _token token to sweep from the contract
* @dev this contract should never hold any tokens so there are no protected tokens
*/
function sweep(IERC20 _token) external onlyOwner {
require(_token.balanceOf(address(this)) > 0, "No balance to sweep");
_token.safeTransfer(owner(), _token.balanceOf(address(this)));
}
/// @notice Toggle rebase functionality
function toggleRebase() external onlyOwner {
rebasePaused = !rebasePaused;
emit RebaseToggled(rebasePaused);
}
}
Read Contract
_initialSharesPerFragment 0xbc02f3f7 → uint256
_sharesPerFragment 0x6f97854c → uint256
allowance 0xdd62ed3e → uint256
balanceOf 0x70a08231 → uint256
decimals 0x313ce567 → uint8
fragmentsToShares 0x13ca42e8 → uint256
isOwner 0x8f32d59b → bool
monetaryPolicy 0x8e27d7d7 → address
name 0x06fdde03 → string
owner 0x8da5cb5b → address
rebaseStartTime 0xb8fd8e73 → uint256
scaledSharesToShares 0xfb334b55 → uint256
sharesOf 0xf5eb42dc → uint256
sharesToFragments 0x5d2dde1d → uint256
sharesToScaledShares 0x6fafb236 → uint256
symbol 0x95d89b41 → string
totalShares 0x3a98ef39 → uint256
totalSupply 0x18160ddd → uint256
Write Contract 14 functions
These functions modify contract state and require a wallet transaction to execute.
approve 0x095ea7b3
address spender
uint256 value
returns: bool
decreaseAllowance 0xa457c2d7
address spender
uint256 subtractedValue
returns: bool
increaseAllowance 0x39509351
address spender
uint256 addedValue
returns: bool
initialize 0x1624f6c6
string name
string symbol
uint8 decimals
initialize 0xc4d66de8
address owner_
oneTimeMint 0xf2301efa
No parameters
rebase 0x7a43e23f
uint256 epoch
int256 supplyDelta
returns: uint256
renounceOwnership 0x715018a6
No parameters
setMonetaryPolicy 0x8b5a6a08
address monetaryPolicy_
sweep 0x01681a62
address _token
toggleRebase 0x786ffeb8
No parameters
transfer 0xa9059cbb
address to
uint256 value
returns: bool
transferFrom 0x23b872dd
address from
address to
uint256 value
returns: bool
transferOwnership 0xf2fde38b
address newOwner
Recent Transactions
No transactions found for this address