├── README.md └── contracts ├── AddressListLibrary.sol └── ScoutHubToken.sol /README.md: -------------------------------------------------------------------------------- 1 | # smart-contract 2 | ScoutHUB - Hub token smart contract repo... 3 | Hub token is BEP20 token which was deployed on binance smart chain... 4 | Our contract address is : 0xee7B7c840de85ad277CdddaEf63b3b29672a3C58 5 | Bsc tracker : https://bscscan.com/address/0xee7B7c840de85ad277CdddaEf63b3b29672a3C58 6 | -------------------------------------------------------------------------------- /contracts/AddressListLibrary.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.9; 3 | 4 | library AddressListLibrary { 5 | using AddressListLibrary for Addresses; 6 | 7 | struct Addresses { 8 | address[] _items; 9 | } 10 | 11 | /** 12 | * @notice push an address to the array 13 | * @dev if the address already exists, it will not be added again 14 | * @param self Storage array containing address type variables 15 | * @param element the element to add in the array 16 | */ 17 | function pushAddress(Addresses storage self, address element) internal { 18 | if (!exists(self, element)) { 19 | self._items.push(element); 20 | } 21 | } 22 | 23 | /** 24 | * @notice get the address at a specific index range from array 25 | * @dev revert if the index is out of bounds 26 | * @param self Storage array containing address type variables 27 | */ 28 | function getAddressesByIndexRange( 29 | Addresses storage self, 30 | uint256 start, 31 | uint256 end 32 | ) internal view returns (address[] memory) { 33 | require( 34 | start < size(self) && end <= size(self) && end - start > 0, 35 | "wrong index range" 36 | ); 37 | uint256 totalSize = end - start; 38 | address[] memory _addresses = new address[](totalSize); 39 | for (uint256 index = 0; index < totalSize; index++) { 40 | _addresses[index] = self._items[index + start]; 41 | } 42 | return _addresses; 43 | } 44 | 45 | /** 46 | * @notice get the size of the array 47 | * @param self Storage array containing address type variables 48 | */ 49 | function size(Addresses storage self) internal view returns (uint256) { 50 | return self._items.length; 51 | } 52 | 53 | /** 54 | * @notice check if an element exist in the array 55 | * @param self Storage array containing address type variables 56 | * @param element the element to check if it exists in the array 57 | */ 58 | function exists(Addresses storage self, address element) 59 | internal 60 | view 61 | returns (bool) 62 | { 63 | for (uint256 i = 0; i < self.size(); i++) { 64 | if (self._items[i] == element) { 65 | return true; 66 | } 67 | } 68 | return false; 69 | } 70 | 71 | /** 72 | * @notice get the array 73 | * @param self Storage array containing address type variables 74 | */ 75 | function getAllAddresses(Addresses storage self) 76 | internal 77 | view 78 | returns (address[] memory) 79 | { 80 | return self._items; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /contracts/ScoutHubToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.9; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; 7 | import "@openzeppelin/contracts/utils/Context.sol"; 8 | import "@openzeppelin/contracts/access/Ownable.sol"; 9 | import "@openzeppelin/contracts/security/Pausable.sol"; 10 | 11 | /** 12 | * @title ERC20 Token for ScoutHub 13 | * @author 0xVeliUysal, 0xfunTalia, Dozcan, ScoutHUB and Deneth 14 | */ 15 | contract ScoutHUBToken is Context, IERC20, IERC20Metadata, Ownable, Pausable { 16 | string public constant name = "ScoutHUB Token"; // ScoutHUB Project 17 | string public constant symbol = "HUB"; // our ticker is HUB 18 | uint8 public constant decimals = 18; 19 | uint256 public totalSupply = 1_000_000_000 ether; // total supply is 1,000,000,000 20 | uint256 private maxSupply = 1_250_000_000 ether; // maximum supply is 1,250,000,000 21 | 22 | mapping(address => uint256) public balances; 23 | mapping(address => mapping(address => uint256)) public allowed; 24 | 25 | // This is a map of addresses to cooldown times and is triggered on every transfer. 26 | mapping(address => uint32) private cooldowns; 27 | // Some addresses should never have a cooldown, such as exchange addresses. Those can be added here. 28 | mapping(address => bool) private cooldownWhitelist; 29 | uint256 public MEV_COOLDOWN_TIME = 1 minutes; 30 | 31 | event Mint(address indexed minter, address indexed account, uint256 amount); 32 | event Burn(address indexed burner, address indexed account, uint256 amount); 33 | 34 | constructor() { 35 | balances[msg.sender] = totalSupply; 36 | } 37 | 38 | /** 39 | * @notice toggle pause 40 | * This method using for toggling pause for contract 41 | */ 42 | function togglePause() external onlyOwner { 43 | paused() ? _unpause() : _pause(); 44 | } 45 | 46 | /** 47 | * @dev See {IERC20-transfer}. 48 | * 49 | * Requirements: 50 | * 51 | * - `recipient` cannot be the zero address. 52 | * - the caller must have a balance of at least `amount`. 53 | */ 54 | function transfer(address to, uint256 value) 55 | external 56 | whenNotPaused 57 | returns (bool) 58 | { 59 | require(to != address(0), "ERC20: to address is not valid"); 60 | require(value <= balances[msg.sender], "ERC20: insufficient balance"); 61 | 62 | beforeTokenTransfer(msg.sender); 63 | 64 | balances[msg.sender] = balances[msg.sender] - value; 65 | balances[to] = balances[to] + value; 66 | 67 | emit Transfer(msg.sender, to, value); 68 | 69 | afterTokenTransfer(to); 70 | 71 | return true; 72 | } 73 | 74 | /** 75 | * @dev See {IERC20-balanceOf}. 76 | */ 77 | function balanceOf(address account) 78 | external 79 | view 80 | returns (uint256 balance) 81 | { 82 | return balances[account]; 83 | } 84 | 85 | /** 86 | * @dev See {IERC20-approve}. 87 | * 88 | * Requirements: 89 | * 90 | * - `spender` cannot be the zero address. 91 | */ 92 | function approve(address spender, uint256 value) 93 | external 94 | whenNotPaused 95 | returns (bool) 96 | { 97 | allowed[msg.sender][spender] = value; 98 | 99 | emit Approval(msg.sender, spender, value); 100 | 101 | return true; 102 | } 103 | 104 | /** 105 | * @dev See {IERC20-transferFrom}. 106 | * 107 | * Emits an {Approval} event indicating the updated allowance. This is not 108 | * required by the EIP. See the note at the beginning of {ERC20}. 109 | * 110 | * Requirements: 111 | * 112 | * - `sender` and `recipient` cannot be the zero address. 113 | * - `sender` must have a balance of at least `amount`. 114 | * - the caller must have allowance for ``sender``'s tokens of at least 115 | * `amount`. 116 | */ 117 | function transferFrom( 118 | address from, 119 | address to, 120 | uint256 value 121 | ) external whenNotPaused returns (bool) { 122 | require(from != address(0), "ERC20: from address is not valid"); 123 | require(to != address(0), "ERC20: to address is not valid"); 124 | require(value <= balances[from], "ERC20: insufficient balance"); 125 | require(value <= allowed[from][msg.sender], "ERC20: from not allowed"); 126 | 127 | balances[from] = balances[from] - value; 128 | balances[to] = balances[to] + value; 129 | allowed[from][msg.sender] = allowed[from][msg.sender] - value; 130 | 131 | emit Transfer(from, to, value); 132 | 133 | return true; 134 | } 135 | 136 | /** 137 | * @dev See {IERC20-allowance}. 138 | */ 139 | function allowance(address account, address spender) 140 | external 141 | view 142 | whenNotPaused 143 | returns (uint256) 144 | { 145 | return allowed[account][spender]; 146 | } 147 | 148 | /** 149 | * @dev Atomically increases the allowance granted to `spender` by the caller. 150 | * 151 | * This is an alternative to {approve} that can be used as a mitigation for 152 | * problems described in {IERC20-approve}. 153 | * 154 | * Emits an {Approval} event indicating the updated allowance. 155 | * 156 | * Requirements: 157 | * 158 | * - `spender` cannot be the zero address. 159 | */ 160 | function increaseApproval(address spender, uint256 addedValue) 161 | external 162 | whenNotPaused 163 | returns (bool) 164 | { 165 | allowed[msg.sender][spender] = 166 | allowed[msg.sender][spender] + 167 | addedValue; 168 | 169 | emit Approval(msg.sender, spender, allowed[msg.sender][spender]); 170 | 171 | return true; 172 | } 173 | 174 | /** 175 | * @dev Atomically decreases the allowance granted to `spender` by the caller. 176 | * 177 | * This is an alternative to {approve} that can be used as a mitigation for 178 | * problems described in {IERC20-approve}. 179 | * 180 | * Emits an {Approval} event indicating the updated allowance. 181 | * 182 | * Requirements: 183 | * 184 | * - `spender` cannot be the zero address. 185 | * - `spender` must have allowance for the caller of at least 186 | * `subtractedValue`. 187 | */ 188 | function decreaseApproval(address spender, uint256 subtractedValue) 189 | external 190 | whenNotPaused 191 | returns (bool) 192 | { 193 | uint256 oldValue = allowed[msg.sender][spender]; 194 | 195 | if (subtractedValue > oldValue) { 196 | allowed[msg.sender][spender] = 0; 197 | } else { 198 | allowed[msg.sender][spender] = oldValue - subtractedValue; 199 | } 200 | 201 | emit Approval(msg.sender, spender, allowed[msg.sender][spender]); 202 | 203 | return true; 204 | } 205 | 206 | /** 207 | * @notice mint method 208 | * This method using to mint new hub tokens. 209 | */ 210 | function mint(address to, uint256 amount) external whenNotPaused onlyOwner { 211 | require(to != address(0), "ERC20: to address is not valid"); 212 | require(amount > 0, "ERC20: amount is not valid"); 213 | 214 | uint256 totalAmount = totalSupply + amount; 215 | require(totalAmount <= maxSupply, "ERC20: unsufficient max supply"); 216 | 217 | totalSupply = totalAmount; 218 | balances[to] = balances[to] + amount; 219 | 220 | emit Mint(msg.sender, to, amount); 221 | } 222 | 223 | /** 224 | * @notice burn method 225 | * This method is implemented for future business rules. 226 | */ 227 | function burn(address account, uint256 amount) external whenNotPaused { 228 | require(account != address(0), "ERC20: from address is not valid"); 229 | require(msg.sender == account, "ERC20: only your address"); 230 | require(balances[account] >= amount, "ERC20: insufficient balance"); 231 | 232 | balances[account] = balances[account] - amount; 233 | totalSupply = totalSupply - amount; 234 | maxSupply = maxSupply - amount; 235 | 236 | emit Burn(msg.sender, account, amount); 237 | } 238 | 239 | /** 240 | * @dev Hook that is called before any transfer of tokens. This includes 241 | * minting and burning. 242 | * 243 | * Calling conditions: 244 | * 245 | * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 246 | * will be transferred to `to`. 247 | * - when `from` is zero, `amount` tokens will be minted for `to`. 248 | * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 249 | * - `from` and `to` are never both zero. 250 | * 251 | */ 252 | function beforeTokenTransfer( 253 | address from 254 | ) internal virtual { 255 | // If the from address is not in the cooldown whitelist, verify it is not in the cooldown 256 | // period. If it is, prevent the transfer. 257 | if (!cooldownWhitelist[from]) { 258 | // Change the error message according to the customized cooldown time. 259 | require( 260 | cooldowns[from] <= uint32(block.timestamp), 261 | "Please wait before transferring or selling your tokens." 262 | ); 263 | } 264 | } 265 | 266 | /** 267 | * @dev Hook that is called after any transfer of tokens. This includes 268 | * minting and burning. 269 | * 270 | * Calling conditions: 271 | * 272 | * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 273 | * has been transferred to `to`. 274 | * - when `from` is zero, `amount` tokens have been minted for `to`. 275 | * - when `to` is zero, `amount` of ``from``'s tokens have been burned. 276 | * - `from` and `to` are never both zero. 277 | * 278 | */ 279 | function afterTokenTransfer( 280 | address to 281 | ) internal virtual { 282 | // If the to address is not in the cooldown whitelist, add a cooldown to it. 283 | if (!cooldownWhitelist[to]) { 284 | // Add a cooldown to the address receiving the tokens. 285 | cooldowns[to] = uint32(block.timestamp + MEV_COOLDOWN_TIME); 286 | } 287 | } 288 | 289 | /** 290 | * Pass in an address to add it to the cooldown whitelist. 291 | */ 292 | function addCooldownWhitelist(address whitelistAddy) external onlyOwner { 293 | cooldownWhitelist[whitelistAddy] = true; 294 | } 295 | 296 | /** 297 | * Pass in an address to remove it from the cooldown whitelist. 298 | */ 299 | function removeCooldownWhitelist(address whitelistAddy) external onlyOwner { 300 | cooldownWhitelist[whitelistAddy] = false; 301 | } 302 | 303 | function setMEVCooldown(uint256 cooldown) external onlyOwner { 304 | MEV_COOLDOWN_TIME = cooldown; 305 | } 306 | 307 | /* 308 | * @notice fallback method 309 | * 310 | * executed when the `data` field is empty or starts with an unknown function signature 311 | */ 312 | fallback() external { 313 | revert("Something bad happened"); 314 | } 315 | } 316 | --------------------------------------------------------------------------------