Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- ERC20DAOToken
- Optimization enabled
- true
- Compiler version
- v0.8.1+commit.df193b15
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2023-03-14T14:29:16.175859Z
Constructor Arguments
000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000044255445a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044255445a00000000000000000000000000000000000000000000000000000000
Arg [0] (string) : BUDZ
Arg [1] (string) : BUDZ
Arg [2] (uint8) : 18
Contract source code
//NUTRIEMP.CRYPTO // SPDX-License-Identifier: MIXED // Sources flattened with hardhat v2.9.0 https://hardhat.org // File @openzeppelin/contracts/utils/[email protected] // License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with 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 Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } } // File @openzeppelin/contracts/access/[email protected] // License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * 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 Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _setOwner(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { 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 { _setOwner(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"); _setOwner(newOwner); } function _setOwner(address newOwner) private { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } } // File @openzeppelin/contracts/token/ERC20/[email protected] // License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // File @openzeppelin/contracts/token/ERC20/extensions/[email protected] // License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @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); } // File @openzeppelin/contracts/token/ERC20/[email protected] // License-Identifier: MIT pragma solidity ^0.8.0; /** * @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.zeppelin.solutions/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 ERC20 is Context, IERC20, IERC20Metadata { 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. */ constructor(string memory name_, string memory symbol_) { _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: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, 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}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), 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}. * * Requirements: * * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom( address sender, address recipient, uint256 amount ) public virtual override returns (bool) { _transfer(sender, recipient, amount); uint256 currentAllowance = _allowances[sender][_msgSender()]; require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); unchecked { _approve(sender, _msgSender(), currentAllowance - 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) { _approve(_msgSender(), spender, _allowances[_msgSender()][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) { uint256 currentAllowance = _allowances[_msgSender()][spender]; require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(_msgSender(), spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `sender` to `recipient`. * * 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: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer( address sender, address recipient, uint256 amount ) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); uint256 senderBalance = _balances[sender]; require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[sender] = senderBalance - amount; } _balances[recipient] += amount; emit Transfer(sender, recipient, amount); _afterTokenTransfer(sender, recipient, 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; _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; } _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 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 {} } // File @openzeppelin/contracts/security/[email protected] // License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } } // File @openzeppelin/contracts/token/ERC20/extensions/[email protected] // License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev ERC20 token with pausable token transfers, minting and burning. * * Useful for scenarios such as preventing trades until the end of an evaluation * period, or having an emergency switch for freezing all token transfers in the * event of a large bug. */ abstract contract ERC20Pausable is ERC20, Pausable { /** * @dev See {ERC20-_beforeTokenTransfer}. * * Requirements: * * - the contract must not be paused. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual override { super._beforeTokenTransfer(from, to, amount); require(!paused(), "ERC20Pausable: token transfer while paused"); } } // File @openzeppelin/contracts/utils/math/[email protected] // License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a / b + (a % b == 0 ? 0 : 1); } } // File @openzeppelin/contracts/utils/[email protected] // License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Collection of functions related to array types. */ library Arrays { /** * @dev Searches a sorted `array` and returns the first index that contains * a value greater or equal to `element`. If no such index exists (i.e. all * values in the array are strictly less than `element`), the array length is * returned. Time complexity O(log n). * * `array` is expected to be sorted in ascending order, and to contain no * repeated elements. */ function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) { if (array.length == 0) { return 0; } uint256 low = 0; uint256 high = array.length; while (low < high) { uint256 mid = Math.average(low, high); // Note that mid will always be strictly less than high (i.e. it will be a valid array index) // because Math.average rounds down (it does integer division with truncation). if (array[mid] > element) { high = mid; } else { low = mid + 1; } } // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound. if (low > 0 && array[low - 1] == element) { return low - 1; } else { return low; } } } // File @openzeppelin/contracts/utils/[email protected] // License-Identifier: MIT pragma solidity ^0.8.0; /** * @title Counters * @author Matt Condon (@shrugs) * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number * of elements in a mapping, issuing ERC721 ids, or counting request ids. * * Include with `using Counters for Counters.Counter;` */ library Counters { struct Counter { // This variable should never be directly accessed by users of the library: interactions must be restricted to // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add // this feature: see https://github.com/ethereum/solidity/issues/4637 uint256 _value; // default: 0 } function current(Counter storage counter) internal view returns (uint256) { return counter._value; } function increment(Counter storage counter) internal { unchecked { counter._value += 1; } } function decrement(Counter storage counter) internal { uint256 value = counter._value; require(value > 0, "Counter: decrement overflow"); unchecked { counter._value = value - 1; } } function reset(Counter storage counter) internal { counter._value = 0; } } // File @openzeppelin/contracts/token/ERC20/extensions/[email protected] // License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev This contract extends an ERC20 token with a snapshot mechanism. When a snapshot is created, the balances and * total supply at the time are recorded for later access. * * This can be used to safely create mechanisms based on token balances such as trustless dividends or weighted voting. * In naive implementations it's possible to perform a "double spend" attack by reusing the same balance from different * accounts. By using snapshots to calculate dividends or voting power, those attacks no longer apply. It can also be * used to create an efficient ERC20 forking mechanism. * * Snapshots are created by the internal {_snapshot} function, which will emit the {Snapshot} event and return a * snapshot id. To get the total supply at the time of a snapshot, call the function {totalSupplyAt} with the snapshot * id. To get the balance of an account at the time of a snapshot, call the {balanceOfAt} function with the snapshot id * and the account address. * * NOTE: Snapshot policy can be customized by overriding the {_getCurrentSnapshotId} method. For example, having it * return `block.number` will trigger the creation of snapshot at the begining of each new block. When overridding this * function, be careful about the monotonicity of its result. Non-monotonic snapshot ids will break the contract. * * Implementing snapshots for every block using this method will incur significant gas costs. For a gas-efficient * alternative consider {ERC20Votes}. * * ==== Gas Costs * * Snapshots are efficient. Snapshot creation is _O(1)_. Retrieval of balances or total supply from a snapshot is _O(log * n)_ in the number of snapshots that have been created, although _n_ for a specific account will generally be much * smaller since identical balances in subsequent snapshots are stored as a single entry. * * There is a constant overhead for normal ERC20 transfers due to the additional snapshot bookkeeping. This overhead is * only significant for the first transfer that immediately follows a snapshot for a particular account. Subsequent * transfers will have normal cost until the next snapshot, and so on. */ abstract contract ERC20Snapshot is ERC20 { // Inspired by Jordi Baylina's MiniMeToken to record historical balances: // https://github.com/Giveth/minimd/blob/ea04d950eea153a04c51fa510b068b9dded390cb/contracts/MiniMeToken.sol using Arrays for uint256[]; using Counters for Counters.Counter; // Snapshotted values have arrays of ids and the value corresponding to that id. These could be an array of a // Snapshot struct, but that would impede usage of functions that work on an array. struct Snapshots { uint256[] ids; uint256[] values; } mapping(address => Snapshots) private _accountBalanceSnapshots; Snapshots private _totalSupplySnapshots; // Snapshot ids increase monotonically, with the first value being 1. An id of 0 is invalid. Counters.Counter private _currentSnapshotId; /** * @dev Emitted by {_snapshot} when a snapshot identified by `id` is created. */ event Snapshot(uint256 id); /** * @dev Creates a new snapshot and returns its snapshot id. * * Emits a {Snapshot} event that contains the same id. * * {_snapshot} is `internal` and you have to decide how to expose it externally. Its usage may be restricted to a * set of accounts, for example using {AccessControl}, or it may be open to the public. * * [WARNING] * ==== * While an open way of calling {_snapshot} is required for certain trust minimization mechanisms such as forking, * you must consider that it can potentially be used by attackers in two ways. * * First, it can be used to increase the cost of retrieval of values from snapshots, although it will grow * logarithmically thus rendering this attack ineffective in the long term. Second, it can be used to target * specific accounts and increase the cost of ERC20 transfers for them, in the ways specified in the Gas Costs * section above. * * We haven't measured the actual numbers; if this is something you're interested in please reach out to us. * ==== */ function _snapshot() internal virtual returns (uint256) { _currentSnapshotId.increment(); uint256 currentId = _getCurrentSnapshotId(); emit Snapshot(currentId); return currentId; } /** * @dev Get the current snapshotId */ function _getCurrentSnapshotId() internal view virtual returns (uint256) { return _currentSnapshotId.current(); } /** * @dev Retrieves the balance of `account` at the time `snapshotId` was created. */ function balanceOfAt(address account, uint256 snapshotId) public view virtual returns (uint256) { (bool snapshotted, uint256 value) = _valueAt(snapshotId, _accountBalanceSnapshots[account]); return snapshotted ? value : balanceOf(account); } /** * @dev Retrieves the total supply at the time `snapshotId` was created. */ function totalSupplyAt(uint256 snapshotId) public view virtual returns (uint256) { (bool snapshotted, uint256 value) = _valueAt(snapshotId, _totalSupplySnapshots); return snapshotted ? value : totalSupply(); } // Update balance and/or total supply snapshots before the values are modified. This is implemented // in the _beforeTokenTransfer hook, which is executed for _mint, _burn, and _transfer operations. function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual override { super._beforeTokenTransfer(from, to, amount); if (from == address(0)) { // mint _updateAccountSnapshot(to); _updateTotalSupplySnapshot(); } else if (to == address(0)) { // burn _updateAccountSnapshot(from); _updateTotalSupplySnapshot(); } else { // transfer _updateAccountSnapshot(from); _updateAccountSnapshot(to); } } function _valueAt(uint256 snapshotId, Snapshots storage snapshots) private view returns (bool, uint256) { require(snapshotId > 0, "ERC20Snapshot: id is 0"); require(snapshotId <= _getCurrentSnapshotId(), "ERC20Snapshot: nonexistent id"); // When a valid snapshot is queried, there are three possibilities: // a) The queried value was not modified after the snapshot was taken. Therefore, a snapshot entry was never // created for this id, and all stored snapshot ids are smaller than the requested one. The value that corresponds // to this id is the current one. // b) The queried value was modified after the snapshot was taken. Therefore, there will be an entry with the // requested id, and its value is the one to return. // c) More snapshots were created after the requested one, and the queried value was later modified. There will be // no entry for the requested id: the value that corresponds to it is that of the smallest snapshot id that is // larger than the requested one. // // In summary, we need to find an element in an array, returning the index of the smallest value that is larger if // it is not found, unless said value doesn't exist (e.g. when all values are smaller). Arrays.findUpperBound does // exactly this. uint256 index = snapshots.ids.findUpperBound(snapshotId); if (index == snapshots.ids.length) { return (false, 0); } else { return (true, snapshots.values[index]); } } function _updateAccountSnapshot(address account) private { _updateSnapshot(_accountBalanceSnapshots[account], balanceOf(account)); } function _updateTotalSupplySnapshot() private { _updateSnapshot(_totalSupplySnapshots, totalSupply()); } function _updateSnapshot(Snapshots storage snapshots, uint256 currentValue) private { uint256 currentId = _getCurrentSnapshotId(); if (_lastSnapshotId(snapshots.ids) < currentId) { snapshots.ids.push(currentId); snapshots.values.push(currentValue); } } function _lastSnapshotId(uint256[] storage ids) private view returns (uint256) { if (ids.length == 0) { return 0; } else { return ids[ids.length - 1]; } } } // File contracts/interface/IERC20DAOToken.sol // License-Identifier: UNLICENSED pragma solidity ^0.8.0; // Uncomment this line to use console.log // import "hardhat/console.sol"; interface IERC20DAOToken is IERC20 { function snapshot() external returns (uint256); } // File contracts/ERC20DAOToken.sol // License-Identifier: UNLICENSED pragma solidity ^0.8.0; // Uncomment this line to use console.log // import "hardhat/console.sol"; contract ERC20DAOToken is Ownable, ERC20, ERC20Pausable, ERC20Snapshot, IERC20DAOToken { event AuthorizedSnapshotter(address account); event DeauthorizedSnapshotter(address account); // Mapping which stores all addresses allowwed to snapshot mapping(address => bool) public authorizedToSnapshot; uint8 private _decimals; constructor( string memory name, string memory symbol, uint8 decimals_ ) ERC20(name, symbol) { _decimals = decimals_; } function decimals() public view override returns (uint8) { return _decimals; } /** * Mints new tokens. * @param account the account to mint the tokens for * @param amount the amount of tokens to mint. */ function mint(address account, uint256 amount) external onlyOwner { _mint(account, amount); } /** * Burns tokens from an address. * @param account the account to burn the tokens for * @param amount the amount of tokens to burn. */ function burn(address account, uint256 amount) external onlyOwner { _burn(account, amount); } /** * Pauses the token contract preventing any token mint/transfer/burn operations. * Can only be called if the contract is unpaused. */ function pause() external onlyOwner { _pause(); } /** * Unpauses the token contract preventing any token mint/transfer/burn operations * Can only be called if the contract is paused. */ function unpause() external onlyOwner { _unpause(); } function getCurrentSnapshotId() external view returns (uint256) { return _getCurrentSnapshotId(); } /** * Creates a token balance snapshot. Ideally this would be called by the * controlling DAO whenever a proposal is made. */ function snapshot() external override returns (uint256) { require( authorizedToSnapshot[_msgSender()] || _msgSender() == owner(), "Not authorized to snapshot" ); return _snapshot(); } /** * Authorizes an account to take snapshots * @param account The account to authorize */ function authorizeSnapshotter(address account) external onlyOwner { require(!authorizedToSnapshot[account], "Account already authorized"); authorizedToSnapshot[account] = true; emit AuthorizedSnapshotter(account); } /** * Deauthorizes an account to take snapshots * @param account The account to de-authorize */ function deauthorizeSnapshotter(address account) external onlyOwner { require(authorizedToSnapshot[account], "Account not authorized"); authorizedToSnapshot[account] = false; emit DeauthorizedSnapshotter(account); } /** * Utility function to transfer tokens to many addresses at once. * @param recipients The addresses to send tokens to * @param amount The amount of tokens to send * @return Boolean if the transfer was a success */ function transferBulk(address[] calldata recipients, uint256 amount) external returns (bool) { address sender = _msgSender(); uint256 total = amount * recipients.length; require( balanceOf(sender) >= total, "ERC20: transfer amount exceeds balance" ); require(!paused(), "ERC20Pausable: token transfer while paused"); for (uint256 i = 0; i < recipients.length; ++i) { address recipient = recipients[i]; require(recipient != address(0), "ERC20: transfer to the zero address"); _transfer(sender, recipient, amount); } return true; } function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual override(ERC20Pausable, ERC20Snapshot, ERC20) whenNotPaused { super._beforeTokenTransfer(from, to, amount); } }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"string","name":"name","internalType":"string"},{"type":"string","name":"symbol","internalType":"string"},{"type":"uint8","name":"decimals_","internalType":"uint8"}]},{"type":"event","name":"Approval","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"address","name":"spender","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"AuthorizedSnapshotter","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"DeauthorizedSnapshotter","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Paused","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Snapshot","inputs":[{"type":"uint256","name":"id","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Unpaused","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"allowance","inputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"address","name":"spender","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"approve","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"authorizeSnapshotter","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"authorizedToSnapshot","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOfAt","inputs":[{"type":"address","name":"account","internalType":"address"},{"type":"uint256","name":"snapshotId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"burn","inputs":[{"type":"address","name":"account","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deauthorizeSnapshotter","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"decimals","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"decreaseAllowance","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"subtractedValue","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getCurrentSnapshotId","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"increaseAllowance","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"addedValue","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"mint","inputs":[{"type":"address","name":"account","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"pause","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"paused","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"snapshot","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupplyAt","inputs":[{"type":"uint256","name":"snapshotId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transfer","inputs":[{"type":"address","name":"recipient","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transferBulk","inputs":[{"type":"address[]","name":"recipients","internalType":"address[]"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transferFrom","inputs":[{"type":"address","name":"sender","internalType":"address"},{"type":"address","name":"recipient","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"unpause","inputs":[]}]
Contract Creation Code
0x60806040523480156200001157600080fd5b5060405162001ef038038062001ef083398101604081905262000034916200024f565b82826200004a62000044620000a2565b620000a6565b81516200005f906004906020850190620000f6565b50805162000075906005906020840190620000f6565b50506006805460ff19908116909155600c805490911660ff93909316929092179091555062000323915050565b3390565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8280546200010490620002d0565b90600052602060002090601f01602090048101928262000128576000855562000173565b82601f106200014357805160ff191683800117855562000173565b8280016001018555821562000173579182015b828111156200017357825182559160200191906001019062000156565b506200018192915062000185565b5090565b5b8082111562000181576000815560010162000186565b600082601f830112620001ad578081fd5b81516001600160401b0380821115620001ca57620001ca6200030d565b604051601f8301601f19908116603f01168101908282118183101715620001f557620001f56200030d565b8160405283815260209250868385880101111562000211578485fd5b8491505b8382101562000234578582018301518183018401529082019062000215565b838211156200024557848385830101525b9695505050505050565b60008060006060848603121562000264578283fd5b83516001600160401b03808211156200027b578485fd5b62000289878388016200019c565b945060208601519150808211156200029f578384fd5b50620002ae868287016200019c565b925050604084015160ff81168114620002c5578182fd5b809150509250925092565b600281046001821680620002e557607f821691505b602082108114156200030757634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b611bbd80620003336000396000f3fe608060405234801561001057600080fd5b50600436106101a95760003560e01c80638456cb59116100f9578063a9059cbb11610097578063e9825ffa11610071578063e9825ffa14610336578063f2fde38b14610349578063f9cb1da31461035c578063fbc1284f1461036f576101a9565b8063a9059cbb146102fd578063c18e273414610310578063dd62ed3e14610323576101a9565b80639711715a116100d35780639711715a146102bc578063981b24d0146102c45780639dc29fac146102d7578063a457c2d7146102ea576101a9565b80638456cb59146102975780638da5cb5b1461029f57806395d89b41146102b4576101a9565b80633f4ba83a116101665780635439ad86116101405780635439ad861461026c5780635c975abb1461027457806370a082311461027c578063715018a61461028f576101a9565b80633f4ba83a1461023c57806340c10f19146102465780634ee2cd7e14610259576101a9565b806306fdde03146101ae578063095ea7b3146101cc57806318160ddd146101ec57806323b872dd14610201578063313ce567146102145780633950935114610229575b600080fd5b6101b6610382565b6040516101c39190611586565b60405180910390f35b6101df6101da3660046114b1565b610414565b6040516101c3919061157b565b6101f4610432565b6040516101c39190611a96565b6101df61020f366004611476565b610438565b61021c6104d1565b6040516101c39190611a9f565b6101df6102373660046114b1565b6104da565b61024461052e565b005b6102446102543660046114b1565b610577565b6101f46102673660046114b1565b6105c4565b6101f461060d565b6101df61061c565b6101f461028a36600461142a565b610625565b610244610644565b61024461068d565b6102a76106d4565b6040516101c39190611567565b6101b66106e3565b6101f46106f2565b6101f46102d236600461154f565b61076b565b6102446102e53660046114b1565b61079b565b6101df6102f83660046114b1565b6107e4565b6101df61030b3660046114b1565b61085d565b6101df61031e3660046114da565b610871565b6101f4610331366004611444565b61096c565b61024461034436600461142a565b610997565b61024461035736600461142a565b610a69565b6101df61036a36600461142a565b610ada565b61024461037d36600461142a565b610aef565b60606004805461039190611b1b565b80601f01602080910402602001604051908101604052809291908181526020018280546103bd90611b1b565b801561040a5780601f106103df5761010080835404028352916020019161040a565b820191906000526020600020905b8154815290600101906020018083116103ed57829003601f168201915b5050505050905090565b6000610428610421610bba565b8484610bbe565b5060015b92915050565b60035490565b6000610445848484610c72565b6001600160a01b038416600090815260026020526040812081610466610bba565b6001600160a01b03166001600160a01b03168152602001908152602001600020549050828110156104b25760405162461bcd60e51b81526004016104a9906117eb565b60405180910390fd5b6104c6856104be610bba565b858403610bbe565b506001949350505050565b600c5460ff1690565b60006104286104e7610bba565b8484600260006104f5610bba565b6001600160a01b03908116825260208083019390935260409182016000908120918b16815292529020546105299190611aad565b610bbe565b610536610bba565b6001600160a01b03166105476106d4565b6001600160a01b03161461056d5760405162461bcd60e51b81526004016104a990611833565b610575610d9c565b565b61057f610bba565b6001600160a01b03166105906106d4565b6001600160a01b0316146105b65760405162461bcd60e51b81526004016104a990611833565b6105c08282610e0a565b5050565b6001600160a01b0382166000908152600760205260408120819081906105eb908590610ed2565b9150915081610602576105fd85610625565b610604565b805b95945050505050565b6000610617610f7e565b905090565b60065460ff1690565b6001600160a01b0381166000908152600160205260409020545b919050565b61064c610bba565b6001600160a01b031661065d6106d4565b6001600160a01b0316146106835760405162461bcd60e51b81526004016104a990611833565b6105756000610f8a565b610695610bba565b6001600160a01b03166106a66106d4565b6001600160a01b0316146106cc5760405162461bcd60e51b81526004016104a990611833565b610575610fda565b6000546001600160a01b031690565b60606005805461039190611b1b565b6000600b6000610700610bba565b6001600160a01b0316815260208101919091526040016000205460ff1680610747575061072b6106d4565b6001600160a01b031661073c610bba565b6001600160a01b0316145b6107635760405162461bcd60e51b81526004016104a990611999565b610617611035565b600080600061077b846008610ed2565b91509150816107915761078c610432565b610793565b805b949350505050565b6107a3610bba565b6001600160a01b03166107b46106d4565b6001600160a01b0316146107da5760405162461bcd60e51b81526004016104a990611833565b6105c08282611089565b600080600260006107f3610bba565b6001600160a01b039081168252602080830193909352604091820160009081209188168152925290205490508281101561083f5760405162461bcd60e51b81526004016104a9906119d0565b61085361084a610bba565b85858403610bbe565b5060019392505050565b600061042861086a610bba565b8484610c72565b60008061087c610bba565b9050600061088a8585611ae5565b90508061089683610625565b10156108b45760405162461bcd60e51b81526004016104a99061174b565b6108bc61061c565b156108d95760405162461bcd60e51b81526004016104a990611a4c565b60005b8581101561095f57600087878381811061090657634e487b7160e01b600052603260045260246000fd5b905060200201602081019061091b919061142a565b90506001600160a01b0381166109435760405162461bcd60e51b81526004016104a990611610565b61094e848288610c72565b5061095881611b56565b90506108dc565b5060019695505050505050565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b61099f610bba565b6001600160a01b03166109b06106d4565b6001600160a01b0316146109d65760405162461bcd60e51b81526004016104a990611833565b6001600160a01b0381166000908152600b602052604090205460ff16610a0e5760405162461bcd60e51b81526004016104a9906117bb565b6001600160a01b0381166000908152600b602052604090819020805460ff19169055517f51f8ef0f426007e7662fabfb0a7d46d2e383ffe4f627aebfac09c2815468773990610a5e908390611567565b60405180910390a150565b610a71610bba565b6001600160a01b0316610a826106d4565b6001600160a01b031614610aa85760405162461bcd60e51b81526004016104a990611833565b6001600160a01b038116610ace5760405162461bcd60e51b81526004016104a9906116c3565b610ad781610f8a565b50565b600b6020526000908152604090205460ff1681565b610af7610bba565b6001600160a01b0316610b086106d4565b6001600160a01b031614610b2e5760405162461bcd60e51b81526004016104a990611833565b6001600160a01b0381166000908152600b602052604090205460ff1615610b675760405162461bcd60e51b81526004016104a990611868565b6001600160a01b0381166000908152600b602052604090819020805460ff19166001179055517f2e457b8fcc8c01e995f48f89abb9cf6a72dce32622702d6ffa54c372be369ff990610a5e908390611567565b3390565b6001600160a01b038316610be45760405162461bcd60e51b81526004016104a990611925565b6001600160a01b038216610c0a5760405162461bcd60e51b81526004016104a990611709565b6001600160a01b0380841660008181526002602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610c65908590611a96565b60405180910390a3505050565b6001600160a01b038316610c985760405162461bcd60e51b81526004016104a9906118e0565b6001600160a01b038216610cbe5760405162461bcd60e51b81526004016104a990611610565b610cc983838361117b565b6001600160a01b03831660009081526001602052604090205481811015610d025760405162461bcd60e51b81526004016104a99061174b565b6001600160a01b03808516600090815260016020526040808220858503905591851681529081208054849290610d39908490611aad565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610d839190611a96565b60405180910390a3610d96848484611176565b50505050565b610da461061c565b610dc05760405162461bcd60e51b81526004016104a990611653565b6006805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa610df3610bba565b604051610e009190611567565b60405180910390a1565b6001600160a01b038216610e305760405162461bcd60e51b81526004016104a990611a15565b610e3c6000838361117b565b8060036000828254610e4e9190611aad565b90915550506001600160a01b03821660009081526001602052604081208054839290610e7b908490611aad565b90915550506040516001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90610ebe908590611a96565b60405180910390a36105c060008383611176565b60008060008411610ef55760405162461bcd60e51b81526004016104a990611969565b610efd610f7e565b841115610f1c5760405162461bcd60e51b81526004016104a9906115d9565b6000610f2884866111ab565b8454909150811415610f41576000809250925050610f77565b6001846001018281548110610f6657634e487b7160e01b600052603260045260246000fd5b906000526020600020015492509250505b9250929050565b6000610617600a61128a565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b610fe261061c565b15610fff5760405162461bcd60e51b81526004016104a990611791565b6006805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610df3610bba565b6000611041600a61128e565b600061104b610f7e565b90507f8030e83b04d87bef53480e26263266d6ca66863aa8506aca6f2559d18aa1cb678160405161107c9190611a96565b60405180910390a1905090565b6001600160a01b0382166110af5760405162461bcd60e51b81526004016104a99061189f565b6110bb8260008361117b565b6001600160a01b038216600090815260016020526040902054818110156110f45760405162461bcd60e51b81526004016104a990611681565b6001600160a01b0383166000908152600160205260408120838303905560038054849290611123908490611b04565b90915550506040516000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90611166908690611a96565b60405180910390a3611176836000845b505050565b61118361061c565b156111a05760405162461bcd60e51b81526004016104a990611791565b611176838383611297565b81546000906111bc5750600061042c565b82546000905b808210156112265760006111d683836112ef565b9050848682815481106111f957634e487b7160e01b600052603260045260246000fd5b9060005260206000200154111561121257809150611220565b61121d816001611aad565b92505b506111c2565b6000821180156112695750838561123e600185611b04565b8154811061125c57634e487b7160e01b600052603260045260246000fd5b9060005260206000200154145b1561128257611279600183611b04565b9250505061042c565b50905061042c565b5490565b80546001019055565b6112a2838383611311565b6001600160a01b0383166112c6576112b982611341565b6112c161136b565b611176565b6001600160a01b0382166112dd576112b983611341565b6112e683611341565b61117682611341565b60006112fe6002848418611ac5565b61130a90848416611aad565b9392505050565b61131c838383611176565b61132461061c565b156111765760405162461bcd60e51b81526004016104a990611a4c565b6001600160a01b0381166000908152600760205260409020610ad79061136683610625565b611378565b6105756008611366610432565b6000611382610f7e565b90508061138e846113c2565b1015611176578254600180820185556000858152602080822090930193909355938401805494850181558252902090910155565b80546000906113d35750600061063f565b815482906113e390600190611b04565b8154811061140157634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905061063f565b80356001600160a01b038116811461063f57600080fd5b60006020828403121561143b578081fd5b61130a82611413565b60008060408385031215611456578081fd5b61145f83611413565b915061146d60208401611413565b90509250929050565b60008060006060848603121561148a578081fd5b61149384611413565b92506114a160208501611413565b9150604084013590509250925092565b600080604083850312156114c3578182fd5b6114cc83611413565b946020939093013593505050565b6000806000604084860312156114ee578283fd5b833567ffffffffffffffff80821115611505578485fd5b818601915086601f830112611518578485fd5b813581811115611526578586fd5b8760208083028501011115611539578586fd5b6020928301989097509590910135949350505050565b600060208284031215611560578081fd5b5035919050565b6001600160a01b0391909116815260200190565b901515815260200190565b6000602080835283518082850152825b818110156115b257858101830151858201604001528201611596565b818111156115c35783604083870101525b50601f01601f1916929092016040019392505050565b6020808252601d908201527f4552433230536e617073686f743a206e6f6e6578697374656e74206964000000604082015260600190565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526014908201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604082015260600190565b60208082526022908201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604082015261636560f01b606082015260800190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b60208082526026908201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604082015265616c616e636560d01b606082015260800190565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6020808252601690820152751058d8dbdd5b9d081b9bdd08185d5d1a1bdc9a5e995960521b604082015260600190565b60208082526028908201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616040820152676c6c6f77616e636560c01b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601a908201527f4163636f756e7420616c726561647920617574686f72697a6564000000000000604082015260600190565b60208082526021908201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736040820152607360f81b606082015260800190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b60208082526016908201527504552433230536e617073686f743a20696420697320360541b604082015260600190565b6020808252601a908201527f4e6f7420617574686f72697a656420746f20736e617073686f74000000000000604082015260600190565b60208082526025908201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604082015264207a65726f60d81b606082015260800190565b6020808252601f908201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b6020808252602a908201527f45524332305061757361626c653a20746f6b656e207472616e736665722077686040820152691a5b19481c185d5cd95960b21b606082015260800190565b90815260200190565b60ff91909116815260200190565b60008219821115611ac057611ac0611b71565b500190565b600082611ae057634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615611aff57611aff611b71565b500290565b600082821015611b1657611b16611b71565b500390565b600281046001821680611b2f57607f821691505b60208210811415611b5057634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415611b6a57611b6a611b71565b5060010190565b634e487b7160e01b600052601160045260246000fdfea264697066735822122032e252f7b321547e352e911c45fe283b2d408a890a1b5e177edf72af1ee0e3b864736f6c63430008010033000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000044255445a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044255445a00000000000000000000000000000000000000000000000000000000
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106101a95760003560e01c80638456cb59116100f9578063a9059cbb11610097578063e9825ffa11610071578063e9825ffa14610336578063f2fde38b14610349578063f9cb1da31461035c578063fbc1284f1461036f576101a9565b8063a9059cbb146102fd578063c18e273414610310578063dd62ed3e14610323576101a9565b80639711715a116100d35780639711715a146102bc578063981b24d0146102c45780639dc29fac146102d7578063a457c2d7146102ea576101a9565b80638456cb59146102975780638da5cb5b1461029f57806395d89b41146102b4576101a9565b80633f4ba83a116101665780635439ad86116101405780635439ad861461026c5780635c975abb1461027457806370a082311461027c578063715018a61461028f576101a9565b80633f4ba83a1461023c57806340c10f19146102465780634ee2cd7e14610259576101a9565b806306fdde03146101ae578063095ea7b3146101cc57806318160ddd146101ec57806323b872dd14610201578063313ce567146102145780633950935114610229575b600080fd5b6101b6610382565b6040516101c39190611586565b60405180910390f35b6101df6101da3660046114b1565b610414565b6040516101c3919061157b565b6101f4610432565b6040516101c39190611a96565b6101df61020f366004611476565b610438565b61021c6104d1565b6040516101c39190611a9f565b6101df6102373660046114b1565b6104da565b61024461052e565b005b6102446102543660046114b1565b610577565b6101f46102673660046114b1565b6105c4565b6101f461060d565b6101df61061c565b6101f461028a36600461142a565b610625565b610244610644565b61024461068d565b6102a76106d4565b6040516101c39190611567565b6101b66106e3565b6101f46106f2565b6101f46102d236600461154f565b61076b565b6102446102e53660046114b1565b61079b565b6101df6102f83660046114b1565b6107e4565b6101df61030b3660046114b1565b61085d565b6101df61031e3660046114da565b610871565b6101f4610331366004611444565b61096c565b61024461034436600461142a565b610997565b61024461035736600461142a565b610a69565b6101df61036a36600461142a565b610ada565b61024461037d36600461142a565b610aef565b60606004805461039190611b1b565b80601f01602080910402602001604051908101604052809291908181526020018280546103bd90611b1b565b801561040a5780601f106103df5761010080835404028352916020019161040a565b820191906000526020600020905b8154815290600101906020018083116103ed57829003601f168201915b5050505050905090565b6000610428610421610bba565b8484610bbe565b5060015b92915050565b60035490565b6000610445848484610c72565b6001600160a01b038416600090815260026020526040812081610466610bba565b6001600160a01b03166001600160a01b03168152602001908152602001600020549050828110156104b25760405162461bcd60e51b81526004016104a9906117eb565b60405180910390fd5b6104c6856104be610bba565b858403610bbe565b506001949350505050565b600c5460ff1690565b60006104286104e7610bba565b8484600260006104f5610bba565b6001600160a01b03908116825260208083019390935260409182016000908120918b16815292529020546105299190611aad565b610bbe565b610536610bba565b6001600160a01b03166105476106d4565b6001600160a01b03161461056d5760405162461bcd60e51b81526004016104a990611833565b610575610d9c565b565b61057f610bba565b6001600160a01b03166105906106d4565b6001600160a01b0316146105b65760405162461bcd60e51b81526004016104a990611833565b6105c08282610e0a565b5050565b6001600160a01b0382166000908152600760205260408120819081906105eb908590610ed2565b9150915081610602576105fd85610625565b610604565b805b95945050505050565b6000610617610f7e565b905090565b60065460ff1690565b6001600160a01b0381166000908152600160205260409020545b919050565b61064c610bba565b6001600160a01b031661065d6106d4565b6001600160a01b0316146106835760405162461bcd60e51b81526004016104a990611833565b6105756000610f8a565b610695610bba565b6001600160a01b03166106a66106d4565b6001600160a01b0316146106cc5760405162461bcd60e51b81526004016104a990611833565b610575610fda565b6000546001600160a01b031690565b60606005805461039190611b1b565b6000600b6000610700610bba565b6001600160a01b0316815260208101919091526040016000205460ff1680610747575061072b6106d4565b6001600160a01b031661073c610bba565b6001600160a01b0316145b6107635760405162461bcd60e51b81526004016104a990611999565b610617611035565b600080600061077b846008610ed2565b91509150816107915761078c610432565b610793565b805b949350505050565b6107a3610bba565b6001600160a01b03166107b46106d4565b6001600160a01b0316146107da5760405162461bcd60e51b81526004016104a990611833565b6105c08282611089565b600080600260006107f3610bba565b6001600160a01b039081168252602080830193909352604091820160009081209188168152925290205490508281101561083f5760405162461bcd60e51b81526004016104a9906119d0565b61085361084a610bba565b85858403610bbe565b5060019392505050565b600061042861086a610bba565b8484610c72565b60008061087c610bba565b9050600061088a8585611ae5565b90508061089683610625565b10156108b45760405162461bcd60e51b81526004016104a99061174b565b6108bc61061c565b156108d95760405162461bcd60e51b81526004016104a990611a4c565b60005b8581101561095f57600087878381811061090657634e487b7160e01b600052603260045260246000fd5b905060200201602081019061091b919061142a565b90506001600160a01b0381166109435760405162461bcd60e51b81526004016104a990611610565b61094e848288610c72565b5061095881611b56565b90506108dc565b5060019695505050505050565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b61099f610bba565b6001600160a01b03166109b06106d4565b6001600160a01b0316146109d65760405162461bcd60e51b81526004016104a990611833565b6001600160a01b0381166000908152600b602052604090205460ff16610a0e5760405162461bcd60e51b81526004016104a9906117bb565b6001600160a01b0381166000908152600b602052604090819020805460ff19169055517f51f8ef0f426007e7662fabfb0a7d46d2e383ffe4f627aebfac09c2815468773990610a5e908390611567565b60405180910390a150565b610a71610bba565b6001600160a01b0316610a826106d4565b6001600160a01b031614610aa85760405162461bcd60e51b81526004016104a990611833565b6001600160a01b038116610ace5760405162461bcd60e51b81526004016104a9906116c3565b610ad781610f8a565b50565b600b6020526000908152604090205460ff1681565b610af7610bba565b6001600160a01b0316610b086106d4565b6001600160a01b031614610b2e5760405162461bcd60e51b81526004016104a990611833565b6001600160a01b0381166000908152600b602052604090205460ff1615610b675760405162461bcd60e51b81526004016104a990611868565b6001600160a01b0381166000908152600b602052604090819020805460ff19166001179055517f2e457b8fcc8c01e995f48f89abb9cf6a72dce32622702d6ffa54c372be369ff990610a5e908390611567565b3390565b6001600160a01b038316610be45760405162461bcd60e51b81526004016104a990611925565b6001600160a01b038216610c0a5760405162461bcd60e51b81526004016104a990611709565b6001600160a01b0380841660008181526002602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610c65908590611a96565b60405180910390a3505050565b6001600160a01b038316610c985760405162461bcd60e51b81526004016104a9906118e0565b6001600160a01b038216610cbe5760405162461bcd60e51b81526004016104a990611610565b610cc983838361117b565b6001600160a01b03831660009081526001602052604090205481811015610d025760405162461bcd60e51b81526004016104a99061174b565b6001600160a01b03808516600090815260016020526040808220858503905591851681529081208054849290610d39908490611aad565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610d839190611a96565b60405180910390a3610d96848484611176565b50505050565b610da461061c565b610dc05760405162461bcd60e51b81526004016104a990611653565b6006805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa610df3610bba565b604051610e009190611567565b60405180910390a1565b6001600160a01b038216610e305760405162461bcd60e51b81526004016104a990611a15565b610e3c6000838361117b565b8060036000828254610e4e9190611aad565b90915550506001600160a01b03821660009081526001602052604081208054839290610e7b908490611aad565b90915550506040516001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90610ebe908590611a96565b60405180910390a36105c060008383611176565b60008060008411610ef55760405162461bcd60e51b81526004016104a990611969565b610efd610f7e565b841115610f1c5760405162461bcd60e51b81526004016104a9906115d9565b6000610f2884866111ab565b8454909150811415610f41576000809250925050610f77565b6001846001018281548110610f6657634e487b7160e01b600052603260045260246000fd5b906000526020600020015492509250505b9250929050565b6000610617600a61128a565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b610fe261061c565b15610fff5760405162461bcd60e51b81526004016104a990611791565b6006805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610df3610bba565b6000611041600a61128e565b600061104b610f7e565b90507f8030e83b04d87bef53480e26263266d6ca66863aa8506aca6f2559d18aa1cb678160405161107c9190611a96565b60405180910390a1905090565b6001600160a01b0382166110af5760405162461bcd60e51b81526004016104a99061189f565b6110bb8260008361117b565b6001600160a01b038216600090815260016020526040902054818110156110f45760405162461bcd60e51b81526004016104a990611681565b6001600160a01b0383166000908152600160205260408120838303905560038054849290611123908490611b04565b90915550506040516000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90611166908690611a96565b60405180910390a3611176836000845b505050565b61118361061c565b156111a05760405162461bcd60e51b81526004016104a990611791565b611176838383611297565b81546000906111bc5750600061042c565b82546000905b808210156112265760006111d683836112ef565b9050848682815481106111f957634e487b7160e01b600052603260045260246000fd5b9060005260206000200154111561121257809150611220565b61121d816001611aad565b92505b506111c2565b6000821180156112695750838561123e600185611b04565b8154811061125c57634e487b7160e01b600052603260045260246000fd5b9060005260206000200154145b1561128257611279600183611b04565b9250505061042c565b50905061042c565b5490565b80546001019055565b6112a2838383611311565b6001600160a01b0383166112c6576112b982611341565b6112c161136b565b611176565b6001600160a01b0382166112dd576112b983611341565b6112e683611341565b61117682611341565b60006112fe6002848418611ac5565b61130a90848416611aad565b9392505050565b61131c838383611176565b61132461061c565b156111765760405162461bcd60e51b81526004016104a990611a4c565b6001600160a01b0381166000908152600760205260409020610ad79061136683610625565b611378565b6105756008611366610432565b6000611382610f7e565b90508061138e846113c2565b1015611176578254600180820185556000858152602080822090930193909355938401805494850181558252902090910155565b80546000906113d35750600061063f565b815482906113e390600190611b04565b8154811061140157634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905061063f565b80356001600160a01b038116811461063f57600080fd5b60006020828403121561143b578081fd5b61130a82611413565b60008060408385031215611456578081fd5b61145f83611413565b915061146d60208401611413565b90509250929050565b60008060006060848603121561148a578081fd5b61149384611413565b92506114a160208501611413565b9150604084013590509250925092565b600080604083850312156114c3578182fd5b6114cc83611413565b946020939093013593505050565b6000806000604084860312156114ee578283fd5b833567ffffffffffffffff80821115611505578485fd5b818601915086601f830112611518578485fd5b813581811115611526578586fd5b8760208083028501011115611539578586fd5b6020928301989097509590910135949350505050565b600060208284031215611560578081fd5b5035919050565b6001600160a01b0391909116815260200190565b901515815260200190565b6000602080835283518082850152825b818110156115b257858101830151858201604001528201611596565b818111156115c35783604083870101525b50601f01601f1916929092016040019392505050565b6020808252601d908201527f4552433230536e617073686f743a206e6f6e6578697374656e74206964000000604082015260600190565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526014908201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604082015260600190565b60208082526022908201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604082015261636560f01b606082015260800190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b60208082526026908201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604082015265616c616e636560d01b606082015260800190565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6020808252601690820152751058d8dbdd5b9d081b9bdd08185d5d1a1bdc9a5e995960521b604082015260600190565b60208082526028908201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616040820152676c6c6f77616e636560c01b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601a908201527f4163636f756e7420616c726561647920617574686f72697a6564000000000000604082015260600190565b60208082526021908201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736040820152607360f81b606082015260800190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b60208082526016908201527504552433230536e617073686f743a20696420697320360541b604082015260600190565b6020808252601a908201527f4e6f7420617574686f72697a656420746f20736e617073686f74000000000000604082015260600190565b60208082526025908201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604082015264207a65726f60d81b606082015260800190565b6020808252601f908201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b6020808252602a908201527f45524332305061757361626c653a20746f6b656e207472616e736665722077686040820152691a5b19481c185d5cd95960b21b606082015260800190565b90815260200190565b60ff91909116815260200190565b60008219821115611ac057611ac0611b71565b500190565b600082611ae057634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615611aff57611aff611b71565b500290565b600082821015611b1657611b16611b71565b500390565b600281046001821680611b2f57607f821691505b60208210811415611b5057634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415611b6a57611b6a611b71565b5060010190565b634e487b7160e01b600052601160045260246000fdfea264697066735822122032e252f7b321547e352e911c45fe283b2d408a890a1b5e177edf72af1ee0e3b864736f6c63430008010033