From c47e334926e7735ac16a69c1ad8d3dbfd9e78c30 Mon Sep 17 00:00:00 2001 From: Jinal Joshi Date: Sat, 6 Apr 2024 19:19:59 +0530 Subject: [PATCH] Update xap.sol --- Exa Protocol/xap.sol | 744 +++++++++++++++++++++++++++++++++---------- 1 file changed, 572 insertions(+), 172 deletions(-) diff --git a/Exa Protocol/xap.sol b/Exa Protocol/xap.sol index 1c7080e..892381d 100644 --- a/Exa Protocol/xap.sol +++ b/Exa Protocol/xap.sol @@ -1,183 +1,583 @@ +/* + + +███████╗██╗ ██╗ █████╗ ██████╗ ██████╗ ██████╗ ████████╗ ██████╗ ██████╗ ██████╗ ██╗ +██╔════╝╚██╗██╔╝██╔══██╗ ██╔══██╗██╔══██╗██╔═══██╗╚══██╔══╝██╔═══██╗██╔════╝██╔═══██╗██║ +█████╗ ╚███╔╝ ███████║ ██████╔╝██████╔╝██║ ██║ ██║ ██║ ██║██║ ██║ ██║██║ +██╔══╝ ██╔██╗ ██╔══██║ ██╔═══╝ ██╔══██╗██║ ██║ ██║ ██║ ██║██║ ██║ ██║██║ +███████╗██╔╝ ██╗██║ ██║ ██║ ██║ ██║╚██████╔╝ ██║ ╚██████╔╝╚██████╗╚██████╔╝███████╗ +╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝ + + +*/ +// Project website: https://www.exaprotocol.com // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +// File: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Context.sol +// OpenZeppelin Contracts v4.4.1 (utils/Context.sol) + +pragma solidity 0.8.25; + +/** + * @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; + } -// ERC20 Token contract interface -interface Token { - function transfer(address to, uint256 amount) external returns(bool); - function transferFrom(address from, address to, uint256 amount) external returns(bool); - function balanceOf(address to) external returns(uint256); + function _msgData() internal view virtual returns (bytes calldata) { + return msg.data; + } } -contract Vesting { - address public immutable owner; // Contract owner - address public immutable tokenContract; // Address of the token contract - uint256 private immutable onemonth = 31 days; // set onemonth - - // Mapping to store locked token amounts for each wallet - mapping(address => uint256) public lockingWallet; - - // Mapping to store vesting periods for each wallet - mapping(address => uint256) public VestingTime; - - // Mapping to store cliff periods for each wallet - mapping(address => uint256) public cliffperiod; - - // Mapping to store starting withdrawable amount of each wallet - mapping(address => uint256) public readytoUseAmt; - - // Mapping to store unlock dates for each wallet - mapping(address => uint256) public unlockDate; - - // Struct to store withdrawal details - struct _withdrawdetails { - uint256 time; // Timestamp of the withdrawal - uint256 amount; // Amount withdrawn - } - mapping(address=>mapping(uint=>_withdrawdetails)) public withdrawdetails; - // Event to log token withdrawals - event withdraw(address indexed _to, uint256 _amount); - - /** - * @dev Constructor function to initialize the vesting contract. - * @param _tokenContract The address of the token contract. - */ - constructor(address _tokenContract) { - owner = msg.sender; // Set the contract owner - tokenContract = _tokenContract; // Set the address of the token contract - } - - /** - * @dev Function to add investors and initialize vesting parameters for each investor. - * @param _wallet An array of addresses representing the wallets of the investors. - * @param _tokenamount An array of token amounts corresponding to each investor. - * @param _vestingTime An array of vesting periods in months for each investor. - * @param _cliffperiod An array of cliff periods in months for each investor. - * @param _readytoUsePercentage An array of percentages representing the portion of tokens ready to use for each investor. - */ - function addInvestors( - address[] memory _wallet, - uint[] memory _tokenamount, - uint[] memory _vestingTime, - uint[] memory _cliffperiod, - uint[] memory _readytoUsePercentage - ) public { - // Validate input parameter lengths - require( - _wallet.length == _tokenamount.length && - _wallet.length == _vestingTime.length && - _wallet.length == _cliffperiod.length && - _wallet.length == _readytoUsePercentage.length, - "Please check parameter values" - ); - - // Initialize vesting parameters for each wallet - for(uint i = 0; i < _wallet.length; i++) { - lockingWallet[_wallet[i]] = (_tokenamount[i] * (100-_readytoUsePercentage[i])) / 100; // Set the locked token amount for the wallet - VestingTime[_wallet[i]] = _vestingTime[i]; // Set the vesting period for the wallet - cliffperiod[_wallet[i]] = _cliffperiod[i]; // Set the cliff period for the wallet - readytoUseAmt[_wallet[i]]=(_tokenamount[i] * _readytoUsePercentage[i]) / 100; - - // Calculate and set the unlock date for the wallet based on the cliff period - unlockDate[_wallet[i]] = block.timestamp + (_cliffperiod[i] * (31 days)); - } - } - - /** - * @dev View the number of completed vesting months for the specified user. - * @param user The address of the user for whom the completed vesting months are being viewed. - * @return The number of completed vesting months. - */ - function CompletedVestingMonth(address user) public view returns(uint){ - uint vestingMonth = 0; // Initialize the number of completed vesting months - - // Iterate over the vesting periods - for(uint i = 0; i < VestingTime[user]; i++) { - // Ensure the unlock date has passed for the current period - require(unlockDate[user] <= block.timestamp, "Unable to Withdraw"); - - // Check if the current period's unlock date has been reached - if(block.timestamp >= unlockDate[user] + (onemonth * i)) { - // Check if the withdrawal for this period has not already occurred - if(withdrawdetails[user][i].time == 0) { - // Increment the count of completed vesting months - vestingMonth++; - } - } else { - break; // Exit loop if the current period is not yet unlocked - } - } - return vestingMonth; // Return the number of completed vesting months - } - - /** - * @dev View the total vesting amount available for withdrawal by the specified user. - * @param user The address of the user for whom the vesting amount is being viewed. - * @return The total vesting amount available for withdrawal. +// File: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol + + +// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) + + +/** + * @dev Interface of the ERC20 standard as defined in the EIP. + */ +interface IERC20 { + /** + * @dev Emitted when `value` tokens are moved from one account (`from`) to + * another (`to`). + * + * Note that `value` may be zero. + */ + event Transfer(address indexed from, address indexed to, uint256 value); + + /** + * @dev Emitted when the allowance of a `spender` for an `owner` is set by + * a call to {approve}. `value` is the new allowance. + */ + event Approval(address indexed owner, address indexed spender, uint256 value); + + /** + * @dev Returns the amount of tokens in existence. + */ + function totalSupply() external view returns (uint256); + + /** + * @dev Returns the amount of tokens owned by `account`. + */ + function balanceOf(address account) external view returns (uint256); + + /** + * @dev Moves `amount` tokens from the caller's account to `to`. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transfer(address to, uint256 amount) external returns (bool); + + /** + * @dev Returns the remaining number of tokens that `spender` will be + * allowed to spend on behalf of `owner` through {transferFrom}. This is + * zero by default. + * + * This value changes when {approve} or {transferFrom} are called. + */ + function allowance(address owner, address spender) external view returns (uint256); + + /** + * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * IMPORTANT: Beware that changing an allowance with this method brings the risk + * that someone may use both the old and the new allowance by unfortunate + * transaction ordering. One possible solution to mitigate this race + * condition is to first reduce the spender's allowance to 0 and set the + * desired value afterwards: + * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + * + * Emits an {Approval} event. + */ + function approve(address spender, uint256 amount) external returns (bool); + + /** + * @dev Moves `amount` tokens from `from` to `to` using the + * allowance mechanism. `amount` is then deducted from the caller's + * allowance. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transferFrom( + address from, + address to, + uint256 amount + ) external returns (bool); +} + +// File: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/extensions/IERC20Metadata.sol + + +// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) + + +/** + * @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: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol + + +// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/ERC20.sol) + + + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract 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: + * + * - `to` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address to, uint256 amount) public virtual override returns (bool) { + address owner = _msgSender(); + _transfer(owner, to, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on + * `transferFrom`. This is semantically equivalent to an infinite approval. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + address owner = _msgSender(); + _approve(owner, spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * NOTE: Does not update the allowance if the current allowance + * is the maximum `uint256`. + * + * Requirements: + * + * - `from` and `to` cannot be the zero address. + * - `from` must have a balance of at least `amount`. + * - the caller must have allowance for ``from``'s tokens of at least + * `amount`. + */ + function transferFrom( + address from, + address to, + uint256 amount + ) public virtual override returns (bool) { + address spender = _msgSender(); + _spendAllowance(from, spender, amount); + _transfer(from, to, amount); + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + address owner = _msgSender(); + _approve(owner, spender, allowance(owner, spender) + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + address owner = _msgSender(); + uint256 currentAllowance = allowance(owner, spender); + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(owner, spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `from` to `to`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `from` cannot be the zero address. + * - `to` cannot be the zero address. + * - `from` must have a balance of at least `amount`. + */ + function _transfer( + address from, + address to, + uint256 amount + ) internal virtual { + require(from != address(0), "ERC20: transfer from the zero address"); + require(to != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(from, to, amount); + + uint256 fromBalance = _balances[from]; + require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[from] = fromBalance - amount; + // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by + // decrementing then incrementing. + _balances[to] += amount; + } + + emit Transfer(from, to, amount); + + _afterTokenTransfer(from, to, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + unchecked { + // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. + _balances[account] += amount; + } + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + // Overflow not possible: amount <= accountBalance <= totalSupply. + _totalSupply -= amount; + } + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Updates `owner` s allowance for `spender` based on spent `amount`. + * + * Does not update the allowance amount in case of infinite allowance. + * Revert if not enough allowance is available. + * + * Might emit an {Approval} event. + */ + function _spendAllowance( + address owner, + address spender, + uint256 amount + ) internal virtual { + uint256 currentAllowance = allowance(owner, spender); + if (currentAllowance != type(uint256).max) { + require(currentAllowance >= amount, "ERC20: insufficient allowance"); + unchecked { + _approve(owner, spender, currentAllowance - amount); + } + } + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} +} + +// File: contracts/1_Storage.sol + + + +contract ExaProtocol is ERC20 { + + /** + * @dev Constructor function. + * Initializes the ERC20 token with the specified name and symbol. + * + * @notice The constructor sets the initial supply of the token to 1,000,000,000 and mints all of them to the contract deployer. + * + * @dev Total supply of the token is set to 1,000,000,000. + * Minting tokens and assigning them to the contract deployer (msg.sender). */ - function withdrawableAmount(address user) public view returns (uint){ - uint vestingAmt = 0; // Initialize the vesting amount - - // Iterate over the vesting periods - for(uint i = 0; i < VestingTime[user]; i++) { - // Ensure the unlock date has passed for the current period - require(unlockDate[user] <= block.timestamp, "Unable to Withdraw"); + constructor() ERC20("Exa Protocol", "XAP"){ - // Check if the current period's unlock date has been reached - if(block.timestamp >= unlockDate[user] + (onemonth * i)) { - // Check if the withdrawal for this period has not already occurred - if(withdrawdetails[user][i].time == 0) { - // Accumulate the vesting amount - vestingAmt += lockingWallet[user] / VestingTime[user]; - } - } else { - break; // Exit loop if the current period is not yet unlocked - } - } - return readytoUseAmt[user]+vestingAmt; // Return the total vesting amount - } - - /** - * @dev Allows users to withdraw tokens based on a vesting schedule. - * @return A boolean indicating the success of the withdrawal operation. + _mint(msg.sender, 1000000000 * (10**decimals())); + + } + + /** + * @dev Function to return the number of decimals. + * + * @notice This function returns the number of decimal places used to display token amounts, which is 8 in this case. + * + * @return uint8 The number of decimals (always returns 8). */ - function withdrawTokens() public returns (bool){ - // Ensure the sender has a locked wallet - require(lockingWallet[msg.sender] > 0, "Wallet Address is not Exist"); - - uint withdrawAMT = 0; // Initialize the withdrawal amount - - // Iterate over the vesting periods - for(uint i = 1; i <= VestingTime[msg.sender]; i++) { - // Ensure the unlock date has passed for the current period - require(unlockDate[msg.sender] <= block.timestamp, "Unable to Withdraw"); - - // Check if the current period's unlock date has been reached - if(block.timestamp >= unlockDate[msg.sender] + (onemonth * i)) { - // Check if the withdrawal for this period has not already occurred - if(withdrawdetails[msg.sender][i].time == 0) { - // Calculate and accumulate the withdrawal amount - withdrawAMT += lockingWallet[msg.sender] / VestingTime[msg.sender]; - - // Record the withdrawal details - withdrawdetails[msg.sender][i] = _withdrawdetails(block.timestamp, lockingWallet[msg.sender] / VestingTime[msg.sender]); - } - } else { - break; // Exit loop if the current period is not yet unlocked - } - } + function decimals() public pure override returns (uint8) { + return 8; + } - withdrawAMT=withdrawAMT+readytoUseAmt[msg.sender]; - // Transfer the accumulated withdrawal amount to the sender - Token(tokenContract).transfer(msg.sender, withdrawAMT); - readytoUseAmt[msg.sender]=0; - - // Emit an event to log the withdrawal - emit withdraw(msg.sender, withdrawAMT); - - // Return success - return true; + /** + * @dev Function to burn a specific amount of tokens. + * + * @notice This function allows the caller to burn a specific amount of tokens from their balance. + * + * @param amount The amount of tokens to be burned. + */ + function burn(uint256 amount) external { + _burn( msg.sender, amount); } - - }