Address Contract Verified
Address
0xD708e5620f5769F65D018a3c97d63aBFeB8Ed019
Balance
0 ETH
Nonce
1
Code Size
7636 bytes
Creator
0x09143c00...Ca24 at tx 0x8128aeba...aebd56
Indexed Transactions
0
Contract Bytecode
7636 bytes
0x60406080815260048036101561001457600080fd5b600091823560e01c806306fdde0314611556578063075461721461152d578063095ea7b3146115035780631814a5b1146114e457806318160ddd146114c557806323b872dd146113f9578063277dbafb146113dc5780632c4e722e146113bd578063313ce567146113a15780633644e51514611384578063395093511461133457806340c10f19146111e657806342966c68146110e45780634cd88b7614610ba857806364ef6dd414610b8657806370a0823114610b4e578063715018a614610ae757806379ba509714610a635780637ecc2b5614610a3f5780637ecebe0014610a075780638da5cb5b146109de57806395d89b41146108fd578063a457c2d714610859578063a9059cbb14610828578063c3b03fa8146105e2578063cb626ae214610573578063d505accf1461032b578063dd5fbc9a1461030c578063dd62ed3e146102c3578063e30c397814610296578063f2fde38b146102255763fca3b5aa1461018057600080fd5b34610221576020366003190112610221576101996115c4565b6101a16116da565b60cc54926001600160a01b03928385166101f65750501680916bffffffffffffffffffffffff60a01b161760cc557fcec52196e972044edde8689a1b608e459c5946b7f3e5c8cd3d6d8e126d422e1c8280a280f35b906020606492519162461bcd60e51b83528201526005602482015264424130303360d81b6044820152fd5b8280fd5b83346102935760203660031901126102935761023f6115c4565b6102476116da565b609a80546001600160a01b0319166001600160a01b039283169081179091556068549091167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e227008380a380f35b80fd5b8382346102bf57816003193601126102bf57609a5490516001600160a01b039091168152602090f35b5080fd5b8382346102bf57806003193601126102bf57806020926102e16115c4565b6102e96115df565b6001600160a01b0391821683526034865283832091168252845220549051908152f35b8382346102bf57816003193601126102bf5760209060d0549051908152f35b50346102215760e0366003190112610221576103456115c4565b61034d6115df565b9060443592606435906084359560ff871680970361056f576001600160a01b0384811697909360c43591891561053c574282106104f9576103b07f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115611aad565b6103b8611aea565b8a8c526067602052858c209485549560018701905586519360208501967f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c988528d89870152898c1660608701528c608087015260a086015260c085015260c0845260e084019067ffffffffffffffff96858310888411176104e6578289528551902061010086019361190160f01b855261010287015261012286015260428252610160850196828810908811176104d35750858752519020845261018082015260a4356101a08201526101c00152878052602090889060809060015afa156104ca57506104bd946104b8918751169081151591826104c0575b5050611aad565b6119ab565b80f35b14905038806104b1565b513d87823e3d90fd5b634e487b7160e01b8e526041905260248dfd5b634e487b7160e01b8f526041825260248ffd5b845162461bcd60e51b8152602081860152601760248201527f5045524d49545f444541444c494e455f455850495245440000000000000000006044820152606490fd5b845162461bcd60e51b8152602081860152600d60248201526c24a72b20a624a22fa7aba722a960991b6044820152606490fd5b8780fd5b503461022157826003193601126102215760ce546301e1338081018091116105cf5742106105a457826104bd611c19565b906020606492519162461bcd60e51b83528201526005602482015264042413030360dc1b6044820152fd5b634e487b7160e01b845260118352602484fd5b50346102215780600319360112610221578135916024938435918285116107fe57819460ce5460cf54916301e13380958683018084116106af578082116107bb575b508683018084116106af578111610791578593925b6103e8851061064d575b60208a8a51908152f35b80821015610703575b6301e1337f1981019081116106af5792671080e992061ab300908181029181830414901517156106af57670de0b6b3a764000090049368a42118e77bc5af0ac785116106c15760001981146106af576001019392610639565b634e487b7160e01b8752601186528a87fd5b885162461bcd60e51b81526020818801526018818d01527f546869732073686f756c64206e657665722068617070656e00000000000000006044820152606490fd5b969594939291908087890190818a11918261077457808411610786575b8492610774578410610733575050610643565b6107538a9c9261075992869798999a9b9c61075f96971061076c57611bac565b86611b99565b9061182a565b9880831061065657610643565b8e9150611bac565b634e487b7160e01b8952601188528d89fd5b915050869080610720565b875162461bcd60e51b81526020818701526005818c015264212098181960d91b6044820152606490fd5b9093925091670de0b6b3a7640000908181029181830414901517156107ec57671080e992061ab30090049238610624565b634e487b7160e01b8652601185528986fd5b606490600587602087519362461bcd60e51b855284015282015264424130303160d81b6044820152fd5b8382346102bf57806003193601126102bf576020906108526108486115c4565b602435903361184d565b5160018152f35b5091346102935782600319360112610293576108736115c4565b918360243592338152603460205281812060018060a01b03861682526020522054908282106108ac5760208561085285850387336119ab565b608490602086519162461bcd60e51b8352820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152fd5b8382346102bf57816003193601126102bf578051908260375461091f81611732565b808552916001918083169081156109b65750600114610959575b50505061094b826109559403836115f5565b519182918261157b565b0390f35b9450603785527f42a7b7dd785cd69714a189dffb3fd7d7174edc9ece837694ce50f7078f7c31ae5b82861061099e5750505061094b8260206109559582010194610939565b80546020878701810191909152909501948101610981565b61095597508693506020925061094b94915060ff191682840152151560051b82010194610939565b8382346102bf57816003193601126102bf5760685490516001600160a01b039091168152602090f35b8382346102bf5760203660031901126102bf5760209181906001600160a01b03610a2f6115c4565b1681526067845220549051908152f35b8382346102bf57816003193601126102bf57602090610a5c611d60565b9051908152f35b5034610221578260031936011261022157609a54336001600160a01b0390911603610a9257826104bd33611684565b906020608492519162461bcd60e51b8352820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152fd5b8334610293578060031936011261029357610b006116da565b609a80546001600160a01b031990811690915560688054918216905581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b8382346102bf5760203660031901126102bf5760209181906001600160a01b03610b766115c4565b1681526033845220549051908152f35b8382346102bf57816003193601126102bf5760209060cd54600f0b9051908152f35b503461022157806003193601126102215767ffffffffffffffff9180358381116110e057610bd9903690830161162d565b9060249081358581116110dc57610bf3903690830161162d565b9286549560ff90818860081c1615958680976110d0575b80156110ba575b1561106157600198878a60ff198316178c55611050575b50610c41838b5460081c16610c3c81611bb9565b611bb9565b610c4a33611684565b610c5d838b5460081c16610c3c81611bb9565b835182811161103e5780610c72603654611732565b95601f96878111610fcd575b506020908d888411600114610f4e5792610f43575b5050600019600383901b1c1916908a1b176036555b8051918211610f3157610cbc603754611732565b848111610ece575b50602090848311600114610e4a57610d009392918b9183610e3f575b5050600019600383901b1c191690891b176037555b885460081c16611bb9565b46606555610d0c611b04565b6066553315610e005750603554916c050c783eb9b5c85f2a8000000092838101809111610dee576035553387526033602052848720838154019055845183815287600080516020611d7f83398151915260203393a36202a300420191824211610ddd57426301de907f1901928311610ddd57505060ce556001600160801b03801960cd54161760cd558460cf5560d055610da4578280f35b825461ff0019168355519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602090a138808280f35b634e487b7160e01b88526011905286fd5b50634e487b7160e01b87526011825286fd5b606492602086519362461bcd60e51b85528401528201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152fd5b015190503880610ce0565b60378b52929189917f42a7b7dd785cd69714a189dffb3fd7d7174edc9ece837694ce50f7078f7c31ae90601f1983168d5b818110610eb657509583610d009710610e9d575b505050811b01603755610cf5565b015160001960f88460031b161c19169055388080610e8f565b8288015184558d959093019260209283019201610e7b565b60378b527f42a7b7dd785cd69714a189dffb3fd7d7174edc9ece837694ce50f7078f7c31ae8580850160051c82019260208610610f28575b0160051c01908a905b828110610f1d575050610cc4565b8c8155018a90610f0f565b92508192610f06565b634e487b7160e01b8a5260418552858afd5b015190503880610c93565b91908d9450601f198416603684527f4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b8935b818110610fb557508411610f9c575b505050811b01603655610ca8565b015160001960f88460031b161c19169055388080610f8e565b8284015185558f969094019360209384019301610f7f565b90915060368d527f4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b88780850160051c82019260208610611035575b859493910160051c909101908d908f5b83821061102757505050610c7e565b81558594508e91018f611018565b92508192611008565b634e487b7160e01b8b5260418652868bfd5b61ffff1916610101178a5538610c28565b875162461bcd60e51b8152602081870152602e818801527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b50303b158015610c1157506001838a1614610c11565b506001838a1610610c0a565b8680fd5b8480fd5b50823461029357602092836003193601126102bf5780359033156111995733835260338552838320549082821061114b5750819033845260338652038383205580603554036035558251908152600080516020611d7f833981519152843392a35160018152f35b845162461bcd60e51b8152908101869052602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608490fd5b835162461bcd60e51b8152908101859052602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608490fd5b5082346102935781600319360112610293576112006115c4565b60cc5460243592916001600160a01b03918216330361130957169182156112de5760ce546301e1338081018091116112cb574210156112be575b603554611247828261182a565b61124f611d60565b10611293576020955081611273600080516020611d7f83398151915293889361182a565b603555848452603382528584208181540190558551908152a35160018152f35b845162461bcd60e51b81526020818801526005602482015264424130303560d81b6044820152606490fd5b6112c6611c19565b61123a565b634e487b7160e01b835260118652602483fd5b835162461bcd60e51b81526020818701526005602482015264043453030360dc1b6044820152606490fd5b845162461bcd60e51b8152602081880152600560248201526410904c0c0d60da1b6044820152606490fd5b8382346102bf57806003193601126102bf5761085260209261137d6113576115c4565b338352603486528483206001600160a01b0382168452865291849020546024359061182a565b90336119ab565b8382346102bf57816003193601126102bf57602090610a5c611aea565b8382346102bf57816003193601126102bf576020905160128152f35b8382346102bf57816003193601126102bf5760209060cf549051908152f35b8382346102bf57816003193601126102bf57602090610a5c611d28565b509190346102bf5760603660031901126102bf576114156115c4565b61141d6115df565b6001600160a01b03821684526034602090815285852033865290529284902054604435939260018201611459575b60208661085287878761184d565b848210611482575091839161147760209695610852950333836119ab565b91939481935061144b565b606490602087519162461bcd60e51b8352820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152fd5b8382346102bf57816003193601126102bf576020906035549051908152f35b8382346102bf57816003193601126102bf5760209060ce549051908152f35b8382346102bf57806003193601126102bf576020906108526115236115c4565b60243590336119ab565b8382346102bf57816003193601126102bf5760cc5490516001600160a01b039091168152602090f35b8382346102bf57816003193601126102bf576109559061157461176c565b9051918291825b6020808252825181830181905290939260005b8281106115b057505060409293506000838284010152601f8019910116010190565b81810186015184820160400152850161158e565b600435906001600160a01b03821682036115da57565b600080fd5b602435906001600160a01b03821682036115da57565b90601f8019910116810190811067ffffffffffffffff82111761161757604052565b634e487b7160e01b600052604160045260246000fd5b81601f820112156115da5780359067ffffffffffffffff82116116175760405192611662601f8401601f1916602001856115f5565b828452602083830101116115da57816000926020809301838601378301015290565b6bffffffffffffffffffffffff60a01b9081609a5416609a5560685460018060a01b038092168093821617606855167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b6068546001600160a01b031633036116ee57565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b90600182811c92168015611762575b602083101461174c57565b634e487b7160e01b600052602260045260246000fd5b91607f1691611741565b604051906000826036549161178083611732565b8083529260019081811690811561180857506001146117a9575b506117a7925003836115f5565b565b6036600090815291507f4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b85b8483106117ed57506117a793505081016020013861179a565b81935090816020925483858a010152019101909185926117d4565b9050602092506117a794915060ff191682840152151560051b8201013861179a565b9190820180921161183757565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b03908116918215611958571691821561190757600082815260336020526040812054918083106118b35760408282600080516020611d7f83398151915295876020965260338652038282205586815220818154019055604051908152a3565b60405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608490fd5b60405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608490fd5b60405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608490fd5b6001600160a01b03908116918215611a5c5716918215611a0c5760207f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925918360005260348252604060002085600052825280604060002055604051908152a3565b60405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608490fd5b60405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608490fd5b15611ab457565b60405162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa9a4a3a722a960911b6044820152606490fd5b6065544603611af95760665490565b611b01611b04565b90565b611b0c61176c565b6020815191012060405160208101917f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f835260408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a0815260c0810181811067ffffffffffffffff8211176116175760405251902090565b8181029291811591840414171561183757565b9190820391821161183757565b15611bc057565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b60cf5460d05460ce546301e13380908181018091116118375760ce5560cd54600181600f0b0160016001607f1b0319811260016001607f1b03821317611837576001600160801b0316906001600160801b0319161760cd558215600014611cc557507f27e46362a1e6129b6dd539c984ce739291a97128dfcaeca1255e8ac83abd9441915060609068a42118e77bc5af0ac7905b8160cf556040519142835260208301526040820152a1565b808302908382040361183757611cda9161182a565b908160d055670de0b6b3a764000080820291820403611837577f27e46362a1e6129b6dd539c984ce739291a97128dfcaeca1255e8ac83abd944191671080e992061ab3006060920490611cad565b60ce546301e133809081810180911161183757428111611d5b5750611d4b611c19565b60ce549081018091116118375790565b905090565b611b0160d054610759611d7560ce5442611bac565b60cf5490611b9956feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220869d3e2a258008f92ed120ed2cddf71d9dcc6ef6695a3e2cb0dd2d5a8ba7725964736f6c63430008110033
Verified Source Code Full Match
Compiler: v0.8.17+commit.8df45f5f
EVM: london
Optimization: Yes (200 runs)
LT.sol 217 lines
// SPDX-License-Identifier: LGPL-3.0
/**
* @title Light DAO Token
* @author LT Finance
* @notice ERC20 with piecewise-linear mining supply.
* @dev Based on the ERC-20 token standard as defined at https://eips.ethereum.org/EIPS/eip-20
*/
pragma solidity 0.8.17;
import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";
import "../interfaces/ILT.sol";
import "./ERC20Permit.sol";
contract LT is ERC20Permit, Ownable2StepUpgradeable, ILT {
//General constants
uint256 private constant _DAY = 86400;
uint256 private constant _YEAR = _DAY * 365;
/// Allocation:
/// =========
/// total 1 trillion
/// 30% to shareholders (team and investors) with 1 year cliff and 4 years vesting
/// 5% to the treasury reserve
/// 5% to LIGHT Foundation (grants)
///
/// == 40% ==
/// left for inflation: 60%
/// Supply parameters
uint256 private constant _INITIAL_SUPPLY = 400_000_000_000;
/// _INITIAL_SUPPLY * 0.2387
uint256 private constant _INITIAL_RATE = (95_480_000_000 * 10 ** 18) / _YEAR;
uint256 private constant _RATE_REDUCTION_TIME = _YEAR;
/// 2 ** (1/4) * 1e18
uint256 private constant _RATE_REDUCTION_COEFFICIENT = 1189207115002721024;
uint256 private constant _RATE_DENOMINATOR = 10 ** 18;
uint256 private constant _INFLATION_DELAY = 2 * _DAY;
address public minter;
/// Supply variables
int128 public miningEpoch;
uint256 public startEpochTime;
uint256 public rate;
uint256 public startEpochSupply;
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
/**
* @notice Contract constructor
* @param _name Token full name
* @param _symbol Token symbol
*/
function initialize(string memory _name, string memory _symbol) external initializer {
__Ownable2Step_init();
__ERC20_init(_name, _symbol);
__ERC20Permit_init();
uint256 initSupply = _INITIAL_SUPPLY * 10 ** decimals();
_mint(_msgSender(), initSupply);
startEpochTime = block.timestamp + _INFLATION_DELAY - _RATE_REDUCTION_TIME;
miningEpoch = -1;
rate = 0;
startEpochSupply = initSupply;
}
/**
* @dev Update mining rate and supply at the start of the epoch
* Any modifying mining call must also call this
*/
function __updateMiningParameters() internal {
uint256 _rate = rate;
uint256 _startEpochSupply = startEpochSupply;
startEpochTime += _RATE_REDUCTION_TIME;
miningEpoch += 1;
if (_rate == 0) {
_rate = _INITIAL_RATE;
} else {
_startEpochSupply += _rate * _RATE_REDUCTION_TIME;
startEpochSupply = _startEpochSupply;
_rate = (_rate * _RATE_DENOMINATOR) / _RATE_REDUCTION_COEFFICIENT;
}
rate = _rate;
emit UpdateMiningParameters(block.timestamp, _rate, _startEpochSupply);
}
/**
* @notice Update mining rate and supply at the start of the epoch
* @dev Callable by any address, but only once per epoch
* Total supply becomes slightly larger if this function is called late
*/
function updateMiningParameters() external override {
require(block.timestamp >= startEpochTime + _RATE_REDUCTION_TIME, "BA000");
__updateMiningParameters();
}
/**
* @notice Get timestamp of the next mining epoch start
* while simultaneously updating mining parameters
* @return Timestamp of the next epoch
*/
function futureEpochTimeWrite() external override returns (uint256) {
uint256 _startEpochTime = startEpochTime;
if (block.timestamp >= _startEpochTime + _RATE_REDUCTION_TIME) {
__updateMiningParameters();
return startEpochTime + _RATE_REDUCTION_TIME;
} else {
return _startEpochTime + _RATE_REDUCTION_TIME;
}
}
function __availableSupply() internal view returns (uint256) {
return startEpochSupply + (block.timestamp - startEpochTime) * rate;
}
/**
* @notice Current number of tokens in existence (claimed or unclaimed)
*/
function availableSupply() external view override returns (uint256) {
return __availableSupply();
}
/**
* @notice How much supply is mintable from start timestamp till end timestamp
* @param start Start of the time interval (timestamp)
* @param end End of the time interval (timestamp)
* @return Tokens mintable from `start` till `end`
*/
function mintableInTimeframe(uint256 start, uint256 end) external view override returns (uint256) {
require(start <= end, "BA001");
uint256 toMint = 0;
uint256 currentEpochTime = startEpochTime;
uint256 currentRate = rate;
// Special case if end is in future (not yet minted) epoch
if (end > currentEpochTime + _RATE_REDUCTION_TIME) {
currentEpochTime += _RATE_REDUCTION_TIME;
currentRate = (currentRate * _RATE_DENOMINATOR) / _RATE_REDUCTION_COEFFICIENT;
}
require(end <= currentEpochTime + _RATE_REDUCTION_TIME, "BA002");
// LT will not work in 1000 years. Darn!
for (uint256 i = 0; i < 1000; i++) {
if (end >= currentEpochTime) {
uint256 currentEnd = end;
if (currentEnd > currentEpochTime + _RATE_REDUCTION_TIME) {
currentEnd = currentEpochTime + _RATE_REDUCTION_TIME;
}
uint256 currentStart = start;
if (currentStart >= currentEpochTime + _RATE_REDUCTION_TIME) {
// We should never get here but what if...
break;
} else if (currentStart < currentEpochTime) {
currentStart = currentEpochTime;
}
toMint += currentRate * (currentEnd - currentStart);
if (start >= currentEpochTime) {
break;
}
}
currentEpochTime -= _RATE_REDUCTION_TIME;
//# double-division with rounding made rate a bit less => good
currentRate = (currentRate * _RATE_REDUCTION_COEFFICIENT) / _RATE_DENOMINATOR;
require(currentRate <= _INITIAL_RATE, "This should never happen");
}
return toMint;
}
/**
* @notice Set the minter address
* @dev Only callable once, when minter has not yet been set
* @param _minter Address of the minter
*/
function setMinter(address _minter) external override onlyOwner {
require(minter == address(0), "BA003");
minter = _minter;
emit SetMinter(_minter);
}
/**
* @notice Mint `value` tokens and assign them to `to`
* @dev Emits a Transfer event originating from 0x00
* @param to The account that will receive the created tokens
* @param value The amount that will be created
* @return bool success
*/
function mint(address to, uint256 value) external override returns (bool) {
require(msg.sender == minter, "BA004");
require(to != address(0), "CE000");
if (block.timestamp >= startEpochTime + _RATE_REDUCTION_TIME) {
__updateMiningParameters();
}
uint256 totalSupply = totalSupply() + value;
require(totalSupply <= __availableSupply(), "BA005");
_mint(to, value);
return true;
}
/**
* @notice Burn `value` tokens belonging to `msg.sender`
* @dev Emits a Transfer event with a destination of 0x00
* @param value The amount that will be burned
* @return bool success
*/
function burn(uint256 value) external override returns (bool) {
_burn(msg.sender, value);
return true;
}
}
ILT.sol 69 lines
// SPDX-License-Identifier: LGPL-3.0
pragma solidity 0.8.17;
interface ILT {
/**
* @dev Emitted when LT inflation rate update
*
* Note once a year
*/
event UpdateMiningParameters(uint256 time, uint256 rate, uint256 supply);
/**
* @dev Emitted when set LT minter,can set the minter only once, at creation
*/
event SetMinter(address indexed minter);
function rate() external view returns (uint256);
/**
* @notice Update mining rate and supply at the start of the epoch
* @dev Callable by any address, but only once per epoch
* Total supply becomes slightly larger if this function is called late
*/
function updateMiningParameters() external;
/**
* @notice Get timestamp of the next mining epoch start while simultaneously updating mining parameters
* @return Timestamp of the next epoch
*/
function futureEpochTimeWrite() external returns (uint256);
/**
* @notice Current number of tokens in existence (claimed or unclaimed)
*/
function availableSupply() external view returns (uint256);
/**
* @notice How much supply is mintable from start timestamp till end timestamp
* @param start Start of the time interval (timestamp)
* @param end End of the time interval (timestamp)
* @return Tokens mintable from `start` till `end`
*/
function mintableInTimeframe(uint256 start, uint256 end) external view returns (uint256);
/**
* @notice Set the minter address
* @dev Only callable once, when minter has not yet been set
* @param _minter Address of the minter
*/
function setMinter(address _minter) external;
/**
* @notice Mint `value` tokens and assign them to `to`
* @dev Emits a Transfer event originating from 0x00
* @param to The account that will receive the created tokens
* @param value The amount that will be created
* @return bool success
*/
function mint(address to, uint256 value) external returns (bool);
/**
* @notice Burn `value` tokens belonging to `msg.sender`
* @dev Emits a Transfer event with a destination of 0x00
* @param value The amount that will be burned
* @return bool success
*/
function burn(uint256 value) external returns (bool);
}
ERC20Permit.sol 70 lines
// SPDX-License-Identifier: LGPL-3.0
pragma solidity 0.8.17;
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
contract ERC20Permit is ERC20Upgradeable {
uint256 internal INITIAL_CHAIN_ID;
bytes32 internal INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
function __ERC20Permit_init() internal onlyInitializing {
INITIAL_CHAIN_ID = block.chainid;
INITIAL_DOMAIN_SEPARATOR = _computeDomainSeparator();
}
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual {
require(owner != address(0), "INVALID_OWNER");
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "INVALID_SIGNER");
// Unchecked because the only math done is incrementing
// the owner's nonce which cannot realistically overflow.
unchecked {
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"),
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
),
v,
r,
s
);
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
_approve(owner, spender, value);
}
}
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : _computeDomainSeparator();
}
function _computeDomainSeparator() internal view virtual returns (bytes32) {
return
keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name())),
keccak256("1"),
block.chainid,
address(this)
)
);
}
}
AddressUpgradeable.sol 219 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is 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.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @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].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
ContextUpgradeable.sol 37 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @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 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.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}
OwnableUpgradeable.sol 95 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @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.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* 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.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal onlyInitializing {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the 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 virtual onlyOwner {
_transferOwnership(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 virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
Initializable.sol 165 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized < type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Internal function that returns the initialized version. Returns `_initialized`
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Internal function that returns the initialized version. Returns `_initializing`
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}
ERC20Upgradeable.sol 401 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.0;
import "./IERC20Upgradeable.sol";
import "./extensions/IERC20MetadataUpgradeable.sol";
import "../../utils/ContextUpgradeable.sol";
import "../../proxy/utils/Initializable.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* The default value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {
__ERC20_init_unchained(name_, symbol_);
}
function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the value {ERC20} uses, unless this function is
* overridden;
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual override returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
* - the caller must have allowance for ``from``'s tokens of at least
* `amount`.
*/
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `amount` of tokens from `from` to `to`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
*/
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
// Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
// decrementing then incrementing.
_balances[to] += amount;
}
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
unchecked {
// Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
_balances[account] += amount;
}
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
// Overflow not possible: amount <= accountBalance <= totalSupply.
_totalSupply -= amount;
}
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
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);
}
/**
* @dev Updates `owner` s allowance for `spender` based on spent `amount`.
*
* Does not update the allowance amount in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Might emit an {Approval} event.
*/
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[45] private __gap;
}
IERC20Upgradeable.sol 82 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20Upgradeable {
/**
* @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);
/**
* @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 `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @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 `from` to `to` 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 from,
address to,
uint256 amount
) external returns (bool);
}
Ownable2StepUpgradeable.sol 71 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (access/Ownable2Step.sol)
pragma solidity ^0.8.0;
import "./OwnableUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership} and {acceptOwnership}.
*
* This module is used through inheritance. It will make available all functions
* from parent (Ownable).
*/
abstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {
function __Ownable2Step_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable2Step_init_unchained() internal onlyInitializing {
}
address private _pendingOwner;
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
/**
* @dev Returns the address of the pending owner.
*/
function pendingOwner() public view virtual returns (address) {
return _pendingOwner;
}
/**
* @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual override onlyOwner {
_pendingOwner = newOwner;
emit OwnershipTransferStarted(owner(), newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual override {
delete _pendingOwner;
super._transferOwnership(newOwner);
}
/**
* @dev The new owner accepts the ownership transfer.
*/
function acceptOwnership() external {
address sender = _msgSender();
require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner");
_transferOwnership(sender);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
IERC20MetadataUpgradeable.sol 28 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20Upgradeable.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20MetadataUpgradeable is IERC20Upgradeable {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}
Read Contract
DOMAIN_SEPARATOR 0x3644e515 → bytes32
allowance 0xdd62ed3e → uint256
availableSupply 0x7ecc2b56 → uint256
balanceOf 0x70a08231 → uint256
decimals 0x313ce567 → uint8
miningEpoch 0x64ef6dd4 → int128
mintableInTimeframe 0xc3b03fa8 → uint256
minter 0x07546172 → address
name 0x06fdde03 → string
nonces 0x7ecebe00 → uint256
owner 0x8da5cb5b → address
pendingOwner 0xe30c3978 → address
rate 0x2c4e722e → uint256
startEpochSupply 0xdd5fbc9a → uint256
startEpochTime 0x1814a5b1 → uint256
symbol 0x95d89b41 → string
totalSupply 0x18160ddd → uint256
Write Contract 15 functions
These functions modify contract state and require a wallet transaction to execute.
acceptOwnership 0x79ba5097
No parameters
approve 0x095ea7b3
address spender
uint256 amount
returns: bool
burn 0x42966c68
uint256 value
returns: bool
decreaseAllowance 0xa457c2d7
address spender
uint256 subtractedValue
returns: bool
futureEpochTimeWrite 0x277dbafb
No parameters
returns: uint256
increaseAllowance 0x39509351
address spender
uint256 addedValue
returns: bool
initialize 0x4cd88b76
string _name
string _symbol
mint 0x40c10f19
address to
uint256 value
returns: bool
permit 0xd505accf
address owner
address spender
uint256 value
uint256 deadline
uint8 v
bytes32 r
bytes32 s
renounceOwnership 0x715018a6
No parameters
setMinter 0xfca3b5aa
address _minter
transfer 0xa9059cbb
address to
uint256 amount
returns: bool
transferFrom 0x23b872dd
address from
address to
uint256 amount
returns: bool
transferOwnership 0xf2fde38b
address newOwner
updateMiningParameters 0xcb626ae2
No parameters
Recent Transactions
No transactions found for this address