// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/**
* @dev Interface of the ERC20 standard as defined in the EIP. Does not include
* the optional functions; to access them see `ERC20Detailed`.
*/
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.
*
* > 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
);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
contract Context {
/**
* @return Address of the transaction message sender {msg.sender}
* Returns the msg.sender
*/
function _msgSender() internal view returns (address) {
return msg.sender;
}
}
contract Ownable is Context {
address public _owner;
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
/**
* @param tokenOwner address of the token owner
* Transfers ownership to tokenOwner
*/
constructor(address tokenOwner) {
_transferOwnership(tokenOwner);
}
/**
* @return Address of the owner of the contract
* Returns the owner address
*/
function owner() public view returns (address) {
return _owner;
}
/**
* Modifier that checks if the msg.sender is the owner
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @return Boolean value true if flow was successful
* Only owner can call the function
* Releases ownership to address 0x0
*/
function renounceOwnership() public onlyOwner returns(bool) {
_transferOwnership(address(0));
return true;
}
/**
* @return Boolean value true if flow was successful
* Only owner can call the function
* Releases ownership to address newOwner
*/
function transferOwnership(address newOwner) public onlyOwner returns(bool){
require(
newOwner != address(0),
"Ownable: new owner is the zero address"
);
_transferOwnership(newOwner);
return true;
}
/**
* Sets newOwner as the owner and emits the OwnershipTransferred event
*/
function _transferOwnership(address newOwner) internal {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
// SPDX-License-Identifier: MIT
import "./IERC20.sol";
import "./Ownable.sol";
pragma solidity ^0.8.9;
contract Token is IERC20, Ownable {
string private _name;
string private _symbol;
uint8 private _decimals;
uint8 constant MAX_TAX_FEE_RATE = 6;
uint8[4] private taxPercentages;
uint8 public taxFee;
uint256 public _totalSupply;
uint256 public whaleAmount;
uint256 public totalVestings;
bool public antiWhale;
bool public _enableTax;
address[4] public taxAddresses;
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
mapping(address => bool) private _isExcludedFromFee;
mapping(uint256 => VestingDetails) public vestingID;
mapping(address => uint256[]) receiverIDs;
mapping(address => bool) isWhitelistedFromWhaleAmount;
enum taxAddressType {
taxAddressNewMovies,
taxAddressProfit,
taxAddressDevelopment,
taxAddressUserCredit
}
event whaleAmountUpdated(
uint256 oldAmount,
uint256 newAmount,
uint256 time
);
event antiWhaleUpdated(bool status, uint256 time);
event taxAddressUpdated(address taxAddress, uint256 time, string info);
event UpdatedWhitelistedAddress(address _address, bool isWhitelisted);
event TaxTransfer(
address indexed from,
address[4] indexed to,
uint256[4] indexed value
);
struct VestingDetails {
address receiver;
uint256 amount;
uint256 release;
bool expired;
}
/**
* @dev Constructor.
* @param __name name of the token
* @param __symbol symbol of the token, 3-4 chars is recommended
* @param __decimals number of decimal places of one token unit, 18 is widely used
* @param _taxPercent will be the tax percentage, example: 6%
* @param __totalSupply total supply of tokens in lowest units (depending on decimals)
* @param _antiWhale to enable the antiwhale feature on/off, by default value is false.
* @param _whaleAmount whale amount of tokens in lowest units (depending on decimals)
* @param owner address that gets 100% of token supply
* @param _taxAddresses will be the 4 addresses to which the tax fees will be sent in each token transfer when tax is applicable
* @param _taxPercentages are the ratios of the tax percentage divided between the 4 _taxAddresses for example => [ 10%, 20%, 30%, 40% ]
*/
constructor(
string memory __name,
string memory __symbol,
uint8 __decimals,
uint8 _taxPercent,
uint256 __totalSupply,
bool _antiWhale,
uint256 _whaleAmount,
address owner,
address[4] memory _taxAddresses,
uint8[4] memory _taxPercentages
) Ownable(owner) {
require(owner != address(0), "Owner can't be zero address");
require(
_taxAddresses[0] != address(0) &&
_taxAddresses[1] != address(0) &&
_taxAddresses[2] != address(0) &&
_taxAddresses[3] != address(0),
"Tax addresses cannot be zero address"
);
require(_taxPercent <= MAX_TAX_FEE_RATE, "Exceeded max tax rate limit");
require(
_taxPercentages[0] +
_taxPercentages[1] +
_taxPercentages[2] +
_taxPercentages[3] ==
100,
"Total percentages must equal 100"
);
require(_whaleAmount < __totalSupply, "Whale amount must be lower than total supply");
_name = __name;
_symbol = __symbol;
_decimals = __decimals;
_owner = owner;
whaleAmount = _whaleAmount * 10**__decimals;
antiWhale = _antiWhale;
_totalSupply = __totalSupply * 10**__decimals;
taxFee = _taxPercent;
_enableTax = true;
// set tokenOwnerAddress as owner of all tokens and the owner has the control of antiWhale feature if enabled.
_balances[_owner] = _totalSupply;
// Mapping tax address
taxAddresses[uint256(taxAddressType.taxAddressDevelopment)] = _taxAddresses[uint256(taxAddressType.taxAddressDevelopment)];
taxAddresses[uint256(taxAddressType.taxAddressNewMovies)] = _taxAddresses[uint256(taxAddressType.taxAddressNewMovies)];
taxAddresses[uint256(taxAddressType.taxAddressProfit)] = _taxAddresses[uint256(taxAddressType.taxAddressProfit)];
taxAddresses[uint256(taxAddressType.taxAddressUserCredit)] = _taxAddresses[uint256(taxAddressType.taxAddressUserCredit)];
// Mapping tax percentages
taxPercentages[uint256(taxAddressType.taxAddressDevelopment)] = _taxPercentages[uint256(taxAddressType.taxAddressDevelopment)];
taxPercentages[uint256(taxAddressType.taxAddressNewMovies)] = _taxPercentages[uint256(taxAddressType.taxAddressNewMovies)];
taxPercentages[uint256(taxAddressType.taxAddressProfit)] = _taxPercentages[uint256(taxAddressType.taxAddressProfit)];
taxPercentages[uint256(taxAddressType.taxAddressUserCredit)] = _taxPercentages[uint256(taxAddressType.taxAddressUserCredit)];
// Owner and taxAddresses are excluded from transfer tax fees
_isExcludedFromFee[_owner] = true;
_isExcludedFromFee[address(this)] = true;
_isExcludedFromFee[taxAddresses[uint256(taxAddressType.taxAddressDevelopment)]] = true;
_isExcludedFromFee[taxAddresses[uint256(taxAddressType.taxAddressNewMovies)]] = true;
_isExcludedFromFee[taxAddresses[uint256(taxAddressType.taxAddressProfit)]] = true;
_isExcludedFromFee[taxAddresses[uint256(taxAddressType.taxAddressUserCredit)]] = true;
isWhitelistedFromWhaleAmount[_owner] = true;
isWhitelistedFromWhaleAmount[address(this)] = true;
isWhitelistedFromWhaleAmount[taxAddresses[uint256(taxAddressType.taxAddressDevelopment)]] = true;
isWhitelistedFromWhaleAmount[taxAddresses[uint256(taxAddressType.taxAddressNewMovies)]] = true;
isWhitelistedFromWhaleAmount[taxAddresses[uint256(taxAddressType.taxAddressProfit)]] = true;
isWhitelistedFromWhaleAmount[taxAddresses[uint256(taxAddressType.taxAddressUserCredit)]] = true;
}
/**
* @return the name of the token.
*/
function name() public view returns (string memory) {
return _name;
}
/**
* @return the symbol of the token.
*/
function symbol() public view returns (string memory) {
return _symbol;
}
/**
* @return the number of decimals of the token.
*/
function decimals() public view returns (uint8) {
return _decimals;
}
/**
* @return the total supply of tokens
*/
function totalSupply() public view override returns (uint256) {
return _totalSupply;
}
/**
* @dev Allows the owner to change the whale amount per transaction
* @param _amount The amount of lowest token units to be set as whaleAmount
* @return _success true (bool) if the flow was successful
*/
function updateWhaleAmount(uint256 _amount)
external
onlyOwner
returns (bool _success)
{
require(antiWhale, "Anti whale is turned off");
uint256 oldAmount = whaleAmount;
whaleAmount = _amount;
emit whaleAmountUpdated(oldAmount, whaleAmount, block.timestamp);
return true;
}
/**
* @dev Allows the owner to turn the anti whale feature on/off.
* @param status disable (false) / enable (enable) bool value
* @return _success true (bool) if the flow was successful
*/
function updateAntiWhale(bool status) external onlyOwner returns (bool _success) {
antiWhale = status;
emit antiWhaleUpdated(antiWhale, block.timestamp);
return true;
}
/**
* @dev See `IERC20.approve`.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* @param spender Address of spender
* @param value uint amount that spender is approved by msg.sender to spend
* @return _success bool (true) if flow was successful
*
* Approves spender to spend value tokens from msg.sender
*/
function approve(address spender, uint256 value) public returns (bool _success) {
_approve(msg.sender, spender, value);
return true;
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
*
* @param owner Address of owner of token who sets allowance for spender to use the owner's tokens
* @param spender Address of spender whose allowance is being set by msg.sender
* @param value Value by which spender's allowance is being reduced
* @return _success bool value => true if flow was successful
*
* This is 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 value
) internal returns (bool _success) {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = value;
emit Approval(owner, spender, value);
return true;
}
/**
* @dev See `IERC20.allowance`.
* @param owner Address of the owner of the tokens
* @param spender Address of the spender of the owners's tokens
* @return the amount of token set by owner for spender to spend
*/
function allowance(address owner, address spender)
public
view
returns (uint256)
{
return _allowances[owner][spender];
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* @param spender Address of spender whose allowance is being increased by msg.sender
* @param addedValue Value by which spender's allowance is being increased
* @return _success bool value => true if flow was successful
*
* 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
returns (bool _success)
{
_approve(
msg.sender,
spender,
_allowances[msg.sender][spender] + addedValue
);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* @param spender Address of spender whose allowance is being increased by msg.sender
* @param subtractedValue Value by which spender's allowance is being reduced
* @return _success bool value => true if flow was successful
*
* 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)
external
returns (bool _success)
{
_approve(
msg.sender,
spender,
_allowances[msg.sender][spender] - subtractedValue
);
return true;
}
/**
* @param _address Address of the user
* @param _isWhitelisted boolean (true or false), whether the address must be enabled/disabled from whitelist
* @return success Boolean value => true if flow was successful
* Updates an account's status in the whitelistFromWhaleAmount (enable/disable)
*/
function updateWhitelistedAddressFromWhale(address _address, bool _isWhitelisted) public onlyOwner
returns(bool success){
isWhitelistedFromWhaleAmount[_address] = _isWhitelisted;
emit UpdatedWhitelistedAddress(_address, _isWhitelisted);
return true;
}
/**
* @dev See `IERC20.transferFrom`.
*
* @param sender Address of sender whose is transferring amount to the recipient
* @param recipient Address of the receiver of tokens from the sender
* @param amount Amount of tokens being transferred by sender to the recipient
* @return _success Boolean value => true if flow was successful
*
*Transfers {amount} token from sender to recipient
* 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 `value`.
* - the caller must have allowance for `sender`'s tokens of at least
* `amount`.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool _success) {
uint256 currentAllowance = _allowances[sender][_msgSender()];
require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
_transfer(sender, recipient, amount);
_approve(sender, msg.sender, currentAllowance - amount);
return true;
}
/**
* @dev See `IERC20.transfer`.
* @param recipient Address of the receiver of tokens from the sender
* @param amount Amount of tokens being transferred by sender to the recipient
* @return _success Boolean value true if the flow is successful
* Requirements:
*
* - `recipient` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address recipient, uint256 amount) external returns (bool _success) {
_transfer(msg.sender, recipient, amount);
return true;
}
/**
* @dev Allows the caller to airdrop tokens.
* @param users Addresses of the users.
* @param amounts Token values to the corresponding users.
* @param totalSum Total sum of the tokens to be airdropped to all users.
* @return _success true (bool) if the flow was successful
*/
function multiSend(
address[] memory users,
uint256[] memory amounts,
uint256 totalSum
) external returns (bool _success) {
require(users.length == amounts.length, "Length mismatch");
require(totalSum <= balanceOf(msg.sender), "Not enough balance");
for (uint256 i = 0; i < users.length; i++) {
_transfer(msg.sender, users[i], amounts[i]);
}
return true;
}
/**
* @param from Address of sender whose is transferring amount to the recipient
* @param to Address of the receiver of tokens from the sender
* @param amount Amount of tokens being transferred by sender to the recipient
* @return _success Boolean value => true if flow was successful
* Transfers amount from {from} to {to}
* Checks for antiWhale
* Checks for tax applicability
*/
function _transfer(
address from,
address to,
uint256 amount
) internal returns (bool _success) {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
require(amount > 0, "Transfer amount must be greater than zero");
// Transfer will be taxed if both sender and receiver are not excluded from fee
bool isTaxed = _enableTax &&
(!(_isExcludedFromFee[from] || _isExcludedFromFee[to]));
// Checking for anti-whale
if (antiWhale) {
uint256 tax_amount = 0;
if (isTaxed) tax_amount = (amount * taxFee) / 10**2;
require(
(amount - tax_amount) <= whaleAmount,
"Transfer amount exceeds max amount"
);
//If account is not whitelisted from whale amount, then checking if total balance will be greater than whale amount
if(!isWhitelistedFromWhaleAmount[to]){
require(
balanceOf(to) + amount - tax_amount <= whaleAmount,
"Recipient amount exceeds max amount"
);
}
}
unchecked {
require(balanceOf(from) >= amount, "Amount exceeds balance");
_balances[from] = _balances[from] - amount;
}
// If any account belongs to _isExcludedFromFee account then no tax will be applied
if (!isTaxed) {
// No tax
// SafeMath for addition overflow built-in
_balances[to] += amount;
emit Transfer(from, to, amount);
} else {
// Calculation of Tax amount
uint256 tax_amount = (amount * taxFee) / (10**2);
_transferFee(tax_amount);
// Subtracting tax from transfer amount to receiver
_balances[to] += amount - tax_amount;
emit Transfer(from, to, amount - tax_amount);
}
return true;
}
/**
* @param tax Amount of tokens to be divided between the 4 tax addresses
* @return _success Boolean value => true if flow was successful
* Transfers the tax fee to the tax addresses divided between them in the ratio provided in taxRatios
*/
function _transferFee(uint256 tax) private returns (bool _success) {
uint8[4] storage taxRatios = taxPercentages;
address[4] storage _taxAddresses = taxAddresses;
// Transfers the tax fee to the tax addresses : taxAddressDevelopment, taxAddressNewMovies, taxAddressProfit
uint256 taxAmountDevelopment = (tax * taxRatios[uint256(taxAddressType.taxAddressDevelopment)]) / (100);
uint256 taxAmountNewMovies = (tax * taxRatios[uint256(taxAddressType.taxAddressNewMovies)]) / (100);
uint256 taxAmountProfit = (tax * taxRatios[uint256(taxAddressType.taxAddressProfit)]) / (100);
uint256 taxAmountUserCredit = (tax * taxRatios[uint256(taxAddressType.taxAddressUserCredit)]) / (100);
_balances[_taxAddresses[uint256(taxAddressType.taxAddressDevelopment)]] += taxAmountDevelopment ;
_balances[_taxAddresses[uint256(taxAddressType.taxAddressNewMovies)]] += taxAmountNewMovies;
_balances[_taxAddresses[uint256(taxAddressType.taxAddressProfit)]] += taxAmountProfit;
uint256 totalDivided = taxAmountDevelopment + taxAmountNewMovies + taxAmountProfit + taxAmountUserCredit;
_balances[_taxAddresses[uint256(taxAddressType.taxAddressUserCredit)]] += taxAmountUserCredit + tax - (totalDivided);
return true;
}
/**
* @param account Address of the account to be checked if its excluded from tax fees
* @return _success Boolean value => true if flow was successful
* Checks if account is excluded from tax fee
*/
function isExcludedFromFee(address account) public view returns (bool _success) {
return _isExcludedFromFee[account];
}
/**
* @param applicable Boolean to set the tax applicability as true or false
* @return _success boolean (true) if flow was successful
Changes the tax applicability as provided in the input
*/
function isTaxApplicable(bool applicable)
external
onlyOwner
returns (bool _success)
{
if (_enableTax != applicable) {
_enableTax = applicable;
return true;
}
return false;
}
/**
* @param newAddress Address of the new taxAddress of type {_type}
* @param _type Tax address type, one of the 4 types :
taxAddressNewMovies,
taxAddressProfit,
taxAddressDevelopment,
taxAddressUserCredit
* @return _success Boolean value => true if flow was successful
* Changes tax address of type {_type}
* Includes the previous address in tax fee
* Excludes the new address from tax fee
* Exclude old address from whitelist, and includes the new address
*/
function changeTaxAddress(address newAddress, taxAddressType _type)
external
onlyOwner
returns (bool _success)
{
includeInFee(taxAddresses[uint256(_type)]);
updateWhitelistedAddressFromWhale(taxAddresses[uint256(_type)], false);
updateWhitelistedAddressFromWhale(newAddress, true);
excludeFromFee(newAddress);
taxAddresses[uint256(_type)] = newAddress;
return true;
}
/**
* @param _taxPercentages The ratios of the division of the tax fees between the 4 tax addresses
* @return _success Boolean value => true if flow was successful
* Changes the ratio of tax division between the 4 tax addresses:
taxAddressNewMovies,
taxAddressProfit,
taxAddressDevelopment,
taxAddressUserCredit
*/
function changeTaxPercentages(uint8[4] calldata _taxPercentages)
external
onlyOwner
returns (bool _success)
{
require(
_taxPercentages[0] +
_taxPercentages[1] +
_taxPercentages[2] +
_taxPercentages[3] ==
100,
"Total percentages must equal 100"
);
taxPercentages[uint256(taxAddressType.taxAddressDevelopment)] = _taxPercentages[uint256(taxAddressType.taxAddressDevelopment)];
taxPercentages[uint256(taxAddressType.taxAddressNewMovies)] = _taxPercentages[uint256(taxAddressType.taxAddressNewMovies)];
taxPercentages[uint256(taxAddressType.taxAddressProfit)] = _taxPercentages[uint256(taxAddressType.taxAddressProfit)];
taxPercentages[uint256(taxAddressType.taxAddressUserCredit)] = _taxPercentages[uint256(taxAddressType.taxAddressUserCredit)];
return true;
}
/**
* @param _taxFee Tax rate in percentage to be set by owner
* @return _success Boolean value => true if flow was successful
* Owner can set the tax rate, maximum upto 6%
*/
function changeTaxFeePercent(uint8 _taxFee) external onlyOwner returns (bool _success) {
require(_taxFee <= MAX_TAX_FEE_RATE, "Exceeded max tax rate");
taxFee = _taxFee;
return true;
}
/**
* @param account Address of account to be evicted from taxes during each transfer
* @return _success Boolean value => true if flow was successful
* Account will be evicted from taxes for each transfer
*/
function excludeFromFee(address account) public onlyOwner returns (bool _success) {
_isExcludedFromFee[account] = true;
return true;
}
/**
* @param account Address of account to be applicable to pay taxes during each transfer
* @return _success Boolean value => true if flow was successful
* Account will be applicable to pay taxes for each transfer
*/
function includeInFee(address account) public onlyOwner returns (bool _success) {
_isExcludedFromFee[account] = false;
return true;
}
/**
* @param account Address of account
* @return Number of tokens owned by the account
* Returns the balance of tokens of the account
*/
function balanceOf(address account) public view override returns (uint256) {
return _balances[account];
}
/**
* @param _receiver Address of the receiver of the vesting
* @param _amount Amount of tokens to be locked up for vesting
* @param _release Timestamp of the release time
* @return _success Boolean value true if flow is successful
* Creates a new vesting
*/
function createVesting(
address _receiver,
uint256 _amount,
uint256 _release
) public returns (bool _success) {
require(_receiver != address(0), "Zero receiver address");
require(_amount > 0, "Zero amount");
require(_release > block.timestamp, "Incorrect release time");
totalVestings++;
vestingID[totalVestings] = VestingDetails(
_receiver,
_amount,
_release,
false
);
// Adds the vesting id corresponding to the receiver
receiverIDs[_receiver].push(totalVestings);
require(_transfer(msg.sender, address(this), _amount));
return true;
}
/**
* @param _receivers Arrays of address of receiver of vesting amount
* @param _amounts Array of amounts corresponding to each vesting
* @param _releases Array of release timestamps corresponding to each vesting
* @return _success Boolean value true if flow is successful
* Creates multiple vesting, calls createVesting for each corresponding entry in {_receivers} {_amounts} {_releases}
*/
function createMultipleVesting(
address[] memory _receivers,
uint256[] memory _amounts,
uint256[] memory _releases
) external returns (bool _success) {
require(
_receivers.length == _amounts.length &&
_amounts.length == _releases.length,
"Invalid data"
);
for (uint256 i = 0; i < _receivers.length; i++) {
bool success = createVesting(
_receivers[i],
_amounts[i],
_releases[i]
);
require(success, "Creation of vesting failed");
}
return true;
}
/**
* @param id Id of the vesting
* @return Boolean value true if flow is successful
* Returns the release timestamp of the the vesting
*/
function getReleaseTime(uint256 id) public view returns(uint256){
require(id > 0 && id <= totalVestings, "Id out of bounds");
VestingDetails storage vestingDetail = vestingID[id];
require(!vestingDetail.expired, "ID expired");
return vestingDetail.release;
}
/**
* @param id Id of the vesting
* @return _success Boolean value true if flow is successful
* The receiver of the vesting can claim their vesting if the vesting ID corresponds to their address
* and hasn't expired
*/
function claim(uint256 id) external returns (bool _success) {
require(id > 0 && id <= totalVestings, "Id out of bounds");
VestingDetails storage vestingDetail = vestingID[id];
require(msg.sender == vestingDetail.receiver, "Caller is not the receiver");
require(!vestingDetail.expired, "ID expired");
require(
block.timestamp >= vestingDetail.release,
"Release time not reached"
);
vestingID[id].expired = true;
require(_transfer(
address(this),
vestingDetail.receiver,
vestingDetail.amount
));
return true;
}
/**
* @param user Address of receiver of vesting amount
* @return Array of IDs corresponding to vesting assigned to the user
* Returns the IDs of the vestings , the user corresponds to
*/
function getReceiverIDs(address user)
external
view
returns (uint256[] memory)
{
return receiverIDs[user];
}
}
{
"compilationTarget": {
"Token.sol": "Token"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"string","name":"__name","type":"string"},{"internalType":"string","name":"__symbol","type":"string"},{"internalType":"uint8","name":"__decimals","type":"uint8"},{"internalType":"uint8","name":"_taxPercent","type":"uint8"},{"internalType":"uint256","name":"__totalSupply","type":"uint256"},{"internalType":"bool","name":"_antiWhale","type":"bool"},{"internalType":"uint256","name":"_whaleAmount","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address[4]","name":"_taxAddresses","type":"address[4]"},{"internalType":"uint8[4]","name":"_taxPercentages","type":"uint8[4]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address[4]","name":"to","type":"address[4]"},{"indexed":true,"internalType":"uint256[4]","name":"value","type":"uint256[4]"}],"name":"TaxTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_address","type":"address"},{"indexed":false,"internalType":"bool","name":"isWhitelisted","type":"bool"}],"name":"UpdatedWhitelistedAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"status","type":"bool"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"antiWhaleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"taxAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"},{"indexed":false,"internalType":"string","name":"info","type":"string"}],"name":"taxAddressUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"whaleAmountUpdated","type":"event"},{"inputs":[],"name":"_enableTax","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"antiWhale","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAddress","type":"address"},{"internalType":"enum Token.taxAddressType","name":"_type","type":"uint8"}],"name":"changeTaxAddress","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_taxFee","type":"uint8"}],"name":"changeTaxFeePercent","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8[4]","name":"_taxPercentages","type":"uint8[4]"}],"name":"changeTaxPercentages","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"claim","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_receivers","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"uint256[]","name":"_releases","type":"uint256[]"}],"name":"createMultipleVesting","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_release","type":"uint256"}],"name":"createVesting","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"excludeFromFee","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getReceiverIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getReleaseTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"includeInFee","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isExcludedFromFee","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"applicable","type":"bool"}],"name":"isTaxApplicable","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"users","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256","name":"totalSum","type":"uint256"}],"name":"multiSend","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"taxAddresses","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"taxFee","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalVestings","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"status","type":"bool"}],"name":"updateAntiWhale","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"updateWhaleAmount","outputs":[{"internalType":"bool","name":"_success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bool","name":"_isWhitelisted","type":"bool"}],"name":"updateWhitelistedAddressFromWhale","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"vestingID","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"release","type":"uint256"},{"internalType":"bool","name":"expired","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"whaleAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]