├── .github └── workflows │ ├── codecov.yaml │ ├── solhint-lint.yaml │ └── unit-tests.yaml ├── .gitignore ├── .solcover.js ├── .solhint.json ├── README.md ├── audit ├── 2021-11 Avalaunch AllocationStaking.pdf ├── 2022-01 Avalaunch XAVA Protocol Audit Final.pdf ├── 20220225_Paladin_Avalaunch_Final_Report.pdf ├── 20220324_Paladin_AvalaunchScopeExtension_Final_Report.pdf ├── Avalaunch Audit 2021-08-v2.pdf └── Avalaunch Launchpad Final.pdf ├── contracts ├── Admin.sol ├── AllocationStaking.sol ├── AvalaunchBadgeFactory.sol ├── AvalaunchCollateral.sol ├── AvalaunchMarketplace.sol ├── IERC20.sol ├── KuCoinVestingContract.sol ├── ParticipationVestingPrivate.sol ├── ParticipationVestingSeed.sol ├── XavaToken.sol ├── airdrop │ ├── Airdrop.sol │ ├── AirdropAVAX.sol │ └── AirdropSale.sol ├── farming │ ├── DevToken.sol │ └── FarmingXava.sol ├── interfaces │ ├── IAdmin.sol │ ├── IAllocationStaking.sol │ ├── IAvalaunchMarketplace.sol │ ├── IAvalaunchSale.sol │ ├── IAvalaunchSaleV2.sol │ ├── ICollateral.sol │ ├── IDexalotPortfolio.sol │ ├── IERC20Metadata.sol │ └── ISalesFactory.sol ├── math │ └── SafeMath.sol ├── openzeppelin │ └── TransparentUpgradeableProxy.sol ├── sales │ ├── AvalaunchSale.sol │ ├── AvalaunchSaleV2.sol │ └── SalesFactory.sol └── utils │ └── Context.sol ├── deployments ├── contract-abis.json ├── contract-addresses.json └── proxy-abis.json ├── hardhat.config.js ├── logo.png ├── package.json ├── scripts ├── airdrops │ ├── deploy_AVAXAirdrop-ISA.js │ ├── deploy_AVAXAirdrop-WOOD.js │ ├── deploy_airdrop.js │ ├── deploy_airdropALOT.js │ ├── deploy_airdropAVAX.js │ ├── deploy_airdropCLY.js │ ├── deploy_airdropDEG.js │ ├── deploy_airdropDFIAT.js │ ├── deploy_airdropHEC.js │ ├── deploy_airdropHON.js │ ├── deploy_airdropISA.js │ ├── deploy_airdropSale.js │ └── deploy_vested_airdrop.js ├── configs │ ├── config.json │ └── saleConfig.json ├── deployment │ ├── deploy_collateral_with_proxy.js │ ├── deploy_devtoken.js │ ├── deploy_farm.js │ ├── deploy_marketplace_with_proxy.js │ ├── deploy_mock_token.js │ ├── deploy_sales.js │ ├── deploy_sales_factory.js │ ├── deploy_sales_staging.js │ ├── deploy_sales_staging_v2.js │ ├── deploy_sales_v2.js │ ├── deploy_singletons.js │ ├── deploy_token.js │ ├── deploy_vesting_private.js │ └── deploy_vesting_seed.js ├── distribution │ ├── distributeAVAX.js │ └── distributeXAVA.js ├── getters.js ├── prolongue_farm.js ├── saleChecksum.js ├── saveABi.js ├── setters │ ├── addAdmin.js │ ├── erc20_approve.js │ ├── setAllocationStakingFee.js │ ├── setSalesFactory.js │ ├── setSalesFactoryOnMarketplace.js │ ├── setWithdrawPenalty.js │ └── set_new_sale_implementation.js ├── styling.js ├── tenderly │ └── push_tenderly.js ├── time.js ├── upgrade │ ├── upgradeAllocationStaking.js │ ├── upgradeCollateral.js │ └── upgradeMarketplace.js └── utils.js └── test ├── V2Tests.js ├── admin.js ├── airdrop.js ├── airdropAVAX.js ├── airdropSale.js ├── allocation-staking.js ├── avalaunch-sale.js ├── badge-factory.js ├── collateral.js ├── helpers └── signatures.js ├── sales-factory.js └── xavaToken.js /.github/workflows/codecov.yaml: -------------------------------------------------------------------------------- 1 | name: Codecov - Code Coverage 2 | 'on': 3 | - push 4 | - pull_request 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | strategy: 9 | matrix: 10 | node-version: 11 | - 14.x 12 | steps: 13 | - name: Checkout repository 14 | uses: actions/checkout@v2 15 | with: 16 | fetch-depth: 2 17 | - name: 'Set up Node.js ${{ matrix.node-version }}' 18 | uses: actions/setup-node@v1 19 | with: 20 | node-version: '${{ matrix.node-version }}' 21 | - name: Install dependencies 22 | run: | 23 | git config --global url.https://github.com/.insteadOf git://github.com/ 24 | yarn install 25 | - name: Run tests 26 | run: npx hardhat coverage --network hardhat --testfiles test 27 | - name: Codecov 28 | uses: codecov/codecov-action@v1.5.2 29 | -------------------------------------------------------------------------------- /.github/workflows/solhint-lint.yaml: -------------------------------------------------------------------------------- 1 | name: Solhint Lint 2 | 'on': 3 | - push 4 | - pull_request 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | strategy: 9 | matrix: 10 | node-version: 11 | - 14.x 12 | steps: 13 | - name: Checkout repository 14 | uses: actions/checkout@v2 15 | with: 16 | fetch-depth: 2 17 | - name: 'Set up Node.js ${{ matrix.node-version }}' 18 | uses: actions/setup-node@v1 19 | with: 20 | node-version: '${{ matrix.node-version }}' 21 | - name: Install dependencies 22 | run: | 23 | git config --global url.https://github.com/.insteadOf git://github.com/ 24 | yarn install 25 | - name: Install solhint 26 | run: npm install -g solhint && solhint --init 27 | - name: Lint 28 | run: solhint contracts/*.sol 29 | -------------------------------------------------------------------------------- /.github/workflows/unit-tests.yaml: -------------------------------------------------------------------------------- 1 | name: Unit Tests 2 | 'on': 3 | - push 4 | - pull_request 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | strategy: 9 | matrix: 10 | node-version: 11 | - 14.x 12 | steps: 13 | - name: Checkout repository 14 | uses: actions/checkout@v2 15 | with: 16 | fetch-depth: 2 17 | - name: 'Set up Node.js ${{ matrix.node-version }}' 18 | uses: actions/setup-node@v1 19 | with: 20 | node-version: '${{ matrix.node-version }}' 21 | - name: Install dependencies 22 | run: | 23 | git config --global url.https://github.com/.insteadOf git://github.com/ 24 | yarn install 25 | - name: Run tests 26 | run: npx hardhat test --network hardhat 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | artifacts 2 | .DS_Store 3 | node_modules 4 | cache 5 | yarn.lock 6 | .env 7 | .idea 8 | package-lock.json 9 | .openzeppelin/ 10 | bin/ 11 | -------------------------------------------------------------------------------- /.solcover.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | skipFiles: [ 3 | 'math', 4 | 'utils', 5 | 'farming', 6 | 'KuCoinVestingContract.sol', 7 | 'ParticipationVestingPrivate.sol', 8 | 'ParticipationVestingSeed.sol', 9 | 'sales/AvalaunchSale.sol', 10 | 'openzeppelin/TransparentUpgradeableProxy.sol' 11 | ] 12 | }; 13 | -------------------------------------------------------------------------------- /.solhint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "solhint:default", 3 | "plugins": [], 4 | "rules": { 5 | "max-line-length": ["warn", 130] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Avalaunch protcool implementation 2 | ![unit-tests](https://github.com/avalaunch-app/xava-protocol/actions/workflows/unit-tests.yaml/badge.svg) 3 | ![solhint-lint](https://github.com/avalaunch-app/xava-protocol/actions/workflows/solhint-lint.yaml/badge.svg) 4 | [![codecov](https://codecov.io/gh/avalaunch-app/xava-protocol/branch/staging/graph/badge.svg?token=JxZIQnKZcw)](https://codecov.io/gh/avalaunch-app/xava-protocol) 5 | 6 | _The first protocol, exclusively for the Avalanche ecosystem, to offer promising and innovative projects a fast, secure, and efficient platform for decentralized fundraising._ 7 | 8 | ### Developement instructions 9 | - `$ yarn install` - _Install all dependencies_ 10 | - `$ echo PK="PRIVATE_KEY" > .env` - _Add testing private key_ 11 | - `$ npx hardhat compile` - _Compile all contracts_ 12 | - `$ npx hardhat node` - _Setup node_ 13 | - `$ npx hardhat test` - _Run all tests_ 14 | - `$ npx hardhat test --network hardhat` - _Run all tests without node_ 15 | - `$ npx hardhat coverage --network hardhat --testfiles test/` - _Run full code coverage_ 16 | 17 | - Migrations are inside `scripts/` folder. 18 | - Tests are inside `test/` folder. 19 | 20 | --- 21 | ### XavaToken 22 | - **Deployed to C-Chain*** 23 | - **Token address:** `0xd1c3f94DE7e5B45fa4eDBBA472491a9f4B166FC4` 24 | - **Total supply :** 100000000 XAVA 25 | - **Verified source code:** https://cchain.explorer.avax.network/address/0xd1c3f94DE7e5B45fa4eDBBA472491a9f4B166FC4/contracts 26 | 27 | --- 28 | -------------------------------------------------------------------------------- /audit/2021-11 Avalaunch AllocationStaking.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avalaunch-app/xava-protocol/e5c7d4a1d779ffd9d00d72bd264fb19dbdf2456e/audit/2021-11 Avalaunch AllocationStaking.pdf -------------------------------------------------------------------------------- /audit/2022-01 Avalaunch XAVA Protocol Audit Final.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avalaunch-app/xava-protocol/e5c7d4a1d779ffd9d00d72bd264fb19dbdf2456e/audit/2022-01 Avalaunch XAVA Protocol Audit Final.pdf -------------------------------------------------------------------------------- /audit/20220225_Paladin_Avalaunch_Final_Report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avalaunch-app/xava-protocol/e5c7d4a1d779ffd9d00d72bd264fb19dbdf2456e/audit/20220225_Paladin_Avalaunch_Final_Report.pdf -------------------------------------------------------------------------------- /audit/20220324_Paladin_AvalaunchScopeExtension_Final_Report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avalaunch-app/xava-protocol/e5c7d4a1d779ffd9d00d72bd264fb19dbdf2456e/audit/20220324_Paladin_AvalaunchScopeExtension_Final_Report.pdf -------------------------------------------------------------------------------- /audit/Avalaunch Audit 2021-08-v2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avalaunch-app/xava-protocol/e5c7d4a1d779ffd9d00d72bd264fb19dbdf2456e/audit/Avalaunch Audit 2021-08-v2.pdf -------------------------------------------------------------------------------- /audit/Avalaunch Launchpad Final.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avalaunch-app/xava-protocol/e5c7d4a1d779ffd9d00d72bd264fb19dbdf2456e/audit/Avalaunch Launchpad Final.pdf -------------------------------------------------------------------------------- /contracts/Admin.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: UNLICENSED 2 | pragma solidity 0.6.12; 3 | 4 | contract Admin { 5 | 6 | // Listing all admins 7 | address [] public admins; 8 | 9 | // Modifier for easier checking if user is admin 10 | mapping(address => bool) public isAdmin; 11 | 12 | // Modifier restricting access to only admin 13 | modifier onlyAdmin { 14 | require(isAdmin[msg.sender], "Only admin can call."); 15 | _; 16 | } 17 | 18 | // Constructor to set initial admins during deployment 19 | constructor (address [] memory _admins) public { 20 | for(uint i = 0; i < _admins.length; i++) { 21 | admins.push(_admins[i]); 22 | isAdmin[_admins[i]] = true; 23 | } 24 | } 25 | 26 | function addAdmin( 27 | address _adminAddress 28 | ) 29 | external 30 | onlyAdmin 31 | { 32 | // Can't add 0x address as an admin 33 | require(_adminAddress != address(0x0), "[RBAC] : Admin must be != than 0x0 address"); 34 | // Can't add existing admin 35 | require(!isAdmin[_adminAddress], "[RBAC] : Admin already exists."); 36 | // Add admin to array of admins 37 | admins.push(_adminAddress); 38 | // Set mapping 39 | isAdmin[_adminAddress] = true; 40 | } 41 | 42 | function removeAdmin( 43 | address _adminAddress 44 | ) 45 | external 46 | onlyAdmin 47 | { 48 | // Admin has to exist 49 | require(isAdmin[_adminAddress]); 50 | require(admins.length > 1, "Can not remove all admins since contract becomes unusable."); 51 | uint i = 0; 52 | 53 | while(admins[i] != _adminAddress) { 54 | if(i == admins.length) { 55 | revert("Passed admin address does not exist"); 56 | } 57 | i++; 58 | } 59 | 60 | // Copy the last admin position to the current index 61 | admins[i] = admins[admins.length-1]; 62 | 63 | isAdmin[_adminAddress] = false; 64 | 65 | // Remove the last admin, since it's double present 66 | admins.pop(); 67 | } 68 | 69 | // Fetch all admins 70 | function getAllAdmins() 71 | external 72 | view 73 | returns (address [] memory) 74 | { 75 | return admins; 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /contracts/AvalaunchBadgeFactory.sol: -------------------------------------------------------------------------------- 1 | //"SPDX-License-Identifier: UNLICENSED" 2 | pragma solidity 0.6.12; 3 | 4 | import "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155PausableUpgradeable.sol"; 5 | import "./interfaces/IAdmin.sol"; 6 | 7 | contract AvalaunchBadgeFactory is ERC1155PausableUpgradeable { 8 | 9 | // Admin contract 10 | IAdmin public admin; 11 | 12 | // Contract level uri 13 | string private contractURI; 14 | // Store id of latest badge created 15 | uint256 private lastCreatedBadgeId; 16 | // Mapping badge id to tradeability 17 | mapping (uint256 => bool) private badgeIdToTradeability; 18 | // Mapping badge id to multiplier 19 | mapping (uint256 => uint8) private badgeIdToMultiplier; 20 | // Mapping badge id to minted supply 21 | mapping (uint256 => uint256) private badgeIdToMintedSupply; 22 | // Mapping for verified marketplace contracts 23 | mapping (address => bool) private verifiedMarketplaces; 24 | 25 | // Events 26 | event BadgeCreated(uint256 badgeId, uint8 multiplier, bool tradeability); 27 | event BadgeMinted(uint256 badgeId, address receiver); 28 | event NewURISet(string newUri); 29 | event NewContractURISet(string newContractUri); 30 | event VMarketplaceAdded(address marketplace); 31 | event VMarketplaceRemoved(address marketplace); 32 | 33 | // Restricting calls only to sale admin 34 | modifier onlyAdmin() { 35 | require( 36 | admin.isAdmin(msg.sender), 37 | "Only admin can call this function." 38 | ); 39 | _; 40 | } 41 | 42 | function initialize( 43 | address _admin, 44 | string calldata _uri, 45 | string calldata _contractURI 46 | ) 47 | external 48 | initializer 49 | { 50 | __ERC1155_init(_uri); 51 | 52 | require(_admin != address(0), "Admin cannot be zero address."); 53 | admin = IAdmin(_admin); 54 | 55 | contractURI = _contractURI; 56 | } 57 | 58 | /// @notice Function to pause the nft transfer related ops 59 | function pause() 60 | external 61 | onlyAdmin 62 | { 63 | _pause(); 64 | } 65 | 66 | /// @notice Function to unpause the nft transfer related ops 67 | function unpause() 68 | external 69 | onlyAdmin 70 | { 71 | _unpause(); 72 | } 73 | 74 | /// @notice Uri setter 75 | function setNewUri( 76 | string calldata _uri 77 | ) 78 | external 79 | onlyAdmin 80 | { 81 | _setURI(_uri); 82 | emit NewURISet(_uri); 83 | } 84 | 85 | /// @notice Contract level uri setter 86 | function setNewContractUri( 87 | string calldata _contractURI 88 | ) 89 | external 90 | onlyAdmin 91 | { 92 | contractURI = _contractURI; 93 | emit NewURISet(_contractURI); 94 | } 95 | 96 | /// @notice Verify marketplace contract 97 | function addVerifiedMarketplace( 98 | address _contract 99 | ) 100 | external 101 | onlyAdmin 102 | { 103 | verifiedMarketplaces[_contract] = true; 104 | emit VMarketplaceAdded(_contract); 105 | } 106 | 107 | /// @notice Remove marketplace contract verification 108 | function removeVerifiedMarketplace( 109 | address _contract 110 | ) 111 | external 112 | onlyAdmin 113 | { 114 | verifiedMarketplaces[_contract] = false; 115 | emit VMarketplaceRemoved(_contract); 116 | } 117 | 118 | /// @notice Function to create badges 119 | /// @dev Necessary for minting 120 | function createBadges( 121 | uint256[] calldata badgeIds, 122 | uint8[] calldata multipliers, 123 | bool[] calldata tradeability 124 | ) 125 | external 126 | onlyAdmin 127 | { 128 | // Validate array size 129 | require( 130 | badgeIds.length == multipliers.length && 131 | multipliers.length == tradeability.length, 132 | "Array size mismatch." 133 | ); 134 | 135 | // Create badges 136 | for(uint i = 0; i < badgeIds.length; i++) { 137 | // Require that new badge has proper id 138 | require(badgeIds[i] == lastCreatedBadgeId.add(1), "Invalid badge id."); 139 | // Set new lastly created badge id 140 | lastCreatedBadgeId = badgeIds[i]; 141 | 142 | // Set badge params 143 | badgeIdToTradeability[badgeIds[i]] = tradeability[i]; 144 | badgeIdToMultiplier[badgeIds[i]] = multipliers[i]; 145 | 146 | // Emit event 147 | emit BadgeCreated(badgeIds[i], multipliers[i], tradeability[i]); 148 | } 149 | } 150 | 151 | /// @notice Function to mint badges to users 152 | /** @dev 153 | * isContract check can be safely used in combination with isAdmin modifier. 154 | * Therefore, it is impossible to initiate function call from malicious contract constructor 155 | * and exploit the check. 156 | */ 157 | function mintBadges( 158 | uint256[] calldata badgeIds, 159 | address[] calldata receivers 160 | ) 161 | external 162 | onlyAdmin 163 | { 164 | // Require that array lengths match 165 | require(badgeIds.length == receivers.length, "Array length mismatch."); 166 | 167 | for(uint i = 0; i < badgeIds.length; i++) { 168 | // Require that receiver is not a contract 169 | require( 170 | !AddressUpgradeable.isContract(receivers[i]), 171 | "Cannot mint badge to untrusted contract." 172 | ); 173 | 174 | // Require that badge has been created 175 | require(badgeIds[i] <= lastCreatedBadgeId, "Badge must be created before minting."); 176 | 177 | // Mint badge NFT to user 178 | _mint(receivers[i], badgeIds[i], 1, "0x0"); 179 | emit BadgeMinted(badgeIds[i], receivers[i]); 180 | } 181 | } 182 | 183 | /// @notice Contract level uri getter 184 | function getContractURI() 185 | external 186 | view 187 | returns 188 | (string memory) 189 | { 190 | return contractURI; 191 | } 192 | 193 | /// @notice Badge total supply getter 194 | function getBadgeSupply( 195 | uint badgeId 196 | ) 197 | external 198 | view 199 | returns (uint256) 200 | { 201 | return badgeIdToMintedSupply[badgeId]; 202 | } 203 | 204 | /// @notice Badge multiplier getter 205 | function getBadgeMultiplier( 206 | uint badgeId 207 | ) 208 | external 209 | view 210 | returns (uint256) 211 | { 212 | return badgeIdToMultiplier[badgeId]; 213 | } 214 | 215 | /// @notice Returns id from lastly created badge 216 | function getLastCreatedBadgeId() 217 | external 218 | view 219 | returns (uint256) 220 | { 221 | return lastCreatedBadgeId; 222 | } 223 | 224 | function isMarketplaceVerified( 225 | address marketplace 226 | ) 227 | external 228 | view 229 | returns (bool) 230 | { 231 | return verifiedMarketplaces[marketplace]; 232 | } 233 | 234 | function _beforeTokenTransfer( 235 | address operator, 236 | address from, 237 | address to, 238 | uint256[] memory ids, 239 | uint256[] memory amounts, 240 | bytes memory data 241 | ) 242 | internal 243 | override 244 | { 245 | super._beforeTokenTransfer(operator, from, to, ids, amounts, data); 246 | 247 | // If operation != mint 248 | if(from != address(0)) { 249 | // Require that verified marketplace is transfer operator 250 | require( 251 | verifiedMarketplaces[operator], 252 | "Badges can be traded only through verified marketplaces." 253 | ); 254 | for(uint i = 0; i < ids.length; i++) { 255 | // Require that badges are tradeable prior to transfer 256 | require(badgeIdToTradeability[ids[i]], "Badge not tradeable."); 257 | } 258 | } else { // In case of minting 259 | for(uint i = 0; i < ids.length; i++) { 260 | // Increase total minted supply 261 | badgeIdToMintedSupply[ids[i]] = badgeIdToMintedSupply[ids[i]].add(amounts[i]); 262 | } 263 | } 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /contracts/IERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity >=0.6.0 <0.8.0; 4 | 5 | /** 6 | * @dev Interface of the ERC20 standard as defined in the EIP. 7 | */ 8 | interface IERC20 { 9 | /** 10 | * @dev Returns the amount of tokens in existence. 11 | */ 12 | function totalSupply() external view returns (uint256); 13 | 14 | /** 15 | * @dev Returns the amount of tokens owned by `account`. 16 | */ 17 | function balanceOf(address account) external view returns (uint256); 18 | 19 | /** 20 | * @dev Moves `amount` tokens from the caller's account to `recipient`. 21 | * 22 | * Returns a boolean value indicating whether the operation succeeded. 23 | * 24 | * Emits a {Transfer} event. 25 | */ 26 | function transfer(address recipient, uint256 amount) external returns (bool); 27 | 28 | /** 29 | * @dev Returns the remaining number of tokens that `spender` will be 30 | * allowed to spend on behalf of `owner` through {transferFrom}. This is 31 | * zero by default. 32 | * 33 | * This value changes when {approve} or {transferFrom} are called. 34 | */ 35 | function allowance(address owner, address spender) external view returns (uint256); 36 | 37 | /** 38 | * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 39 | * 40 | * Returns a boolean value indicating whether the operation succeeded. 41 | * 42 | * IMPORTANT: Beware that changing an allowance with this method brings the risk 43 | * that someone may use both the old and the new allowance by unfortunate 44 | * transaction ordering. One possible solution to mitigate this race 45 | * condition is to first reduce the spender's allowance to 0 and set the 46 | * desired value afterwards: 47 | * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 48 | * 49 | * Emits an {Approval} event. 50 | */ 51 | function approve(address spender, uint256 amount) external returns (bool); 52 | 53 | /** 54 | * @dev Moves `amount` tokens from `sender` to `recipient` using the 55 | * allowance mechanism. `amount` is then deducted from the caller's 56 | * allowance. 57 | * 58 | * Returns a boolean value indicating whether the operation succeeded. 59 | * 60 | * Emits a {Transfer} event. 61 | */ 62 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 63 | 64 | /** 65 | * @dev Emitted when `value` tokens are moved from one account (`from`) to 66 | * another (`to`). 67 | * 68 | * Note that `value` may be zero. 69 | */ 70 | event Transfer(address indexed from, address indexed to, uint256 value); 71 | 72 | /** 73 | * @dev Emitted when the allowance of a `spender` for an `owner` is set by 74 | * a call to {approve}. `value` is the new allowance. 75 | */ 76 | event Approval(address indexed owner, address indexed spender, uint256 value); 77 | } 78 | -------------------------------------------------------------------------------- /contracts/KuCoinVestingContract.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.12; 2 | 3 | import "./IERC20.sol"; 4 | import "./math/SafeMath.sol"; 5 | 6 | 7 | contract KuCoinVestingContract { 8 | 9 | IERC20 public token; 10 | using SafeMath for uint256; 11 | 12 | // Address receiving tokens 13 | address public beneficiary; 14 | // Unlocking amounts, can't have length more than 10 15 | uint256[] public unlockingAmounts; 16 | // Unlocking times, can't have length more than 10 17 | uint256[] public unlockingTimes; 18 | // Markers, can't have length more than 10 19 | bool [] public isWithdrawn; 20 | 21 | constructor( 22 | address _beneficiary, 23 | uint256[] memory _unlockingAmounts, 24 | uint256[] memory _unlockingTimes 25 | ) 26 | public 27 | { 28 | require(_beneficiary != address(0), "Beneficiary address can not be 0x0"); 29 | require(_unlockingAmounts.length == _unlockingTimes.length, "Input arguments are not matching!"); 30 | 31 | beneficiary = _beneficiary; 32 | for(uint i=0; i<_unlockingTimes.length; i++) { 33 | unlockingTimes.push(_unlockingTimes[i]); 34 | unlockingAmounts.push(_unlockingAmounts[i]); 35 | } 36 | } 37 | 38 | /// Deposit tokens which should be used to payout the beneficiary over time 39 | function depositTokens( 40 | uint256 amount 41 | ) 42 | public 43 | { 44 | token.transferFrom(msg.sender, address(this), amount); 45 | } 46 | 47 | /// Withdraw function, takes always everything which is available at the moment 48 | function withdraw() 49 | public 50 | { 51 | uint256 totalToPay; 52 | for(uint i=0; i unlockingTimes[i]) { 54 | totalToPay = totalToPay.add(unlockingAmounts[i]); 55 | isWithdrawn[i] = true; 56 | } 57 | } 58 | 59 | if(totalToPay > 0) { 60 | token.transfer(beneficiary, totalToPay); 61 | } 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /contracts/ParticipationVestingPrivate.sol: -------------------------------------------------------------------------------- 1 | //"SPDX-License-Identifier: UNLICENSED" 2 | pragma solidity ^0.6.12; 3 | 4 | import "./math/SafeMath.sol"; 5 | import "./IERC20.sol"; 6 | 7 | /// ParticipationVesting smart contract 8 | contract ParticipationVestingPrivate { 9 | 10 | using SafeMath for *; 11 | 12 | uint public totalTokensToDistribute; 13 | uint public totalTokensWithdrawn; 14 | 15 | struct Participation { 16 | uint256 initialPortion; 17 | uint256 vestedAmount; 18 | uint256 amountPerPortion; 19 | bool initialPortionWithdrawn; 20 | bool [] isVestedPortionWithdrawn; 21 | } 22 | 23 | IERC20 public token; 24 | 25 | address public adminWallet; 26 | mapping(address => Participation) public addressToParticipation; 27 | mapping(address => bool) public hasParticipated; 28 | 29 | uint public initialPortionUnlockingTime; 30 | uint public numberOfPortions; 31 | uint [] distributionDates; 32 | 33 | modifier onlyAdmin { 34 | require(msg.sender == adminWallet, "OnlyAdmin: Restricted access."); 35 | _; 36 | } 37 | 38 | /// Load initial distribution dates 39 | constructor ( 40 | uint _numberOfPortions, 41 | uint timeBetweenPortions, 42 | uint distributionStartDate, 43 | uint _initialPortionUnlockingTime, 44 | address _adminWallet, 45 | address _token 46 | ) 47 | public 48 | { 49 | // Set admin wallet 50 | adminWallet = _adminWallet; 51 | // Store number of portions 52 | numberOfPortions = _numberOfPortions; 53 | 54 | // Time when initial portion is unlocked 55 | initialPortionUnlockingTime = _initialPortionUnlockingTime; 56 | 57 | // Set distribution dates 58 | for(uint i = 0 ; i < _numberOfPortions; i++) { 59 | distributionDates.push(distributionStartDate + i*timeBetweenPortions); 60 | } 61 | // Set the token address 62 | token = IERC20(_token); 63 | } 64 | 65 | // Function to register multiple participants at a time 66 | function registerParticipants( 67 | address [] memory participants, 68 | uint256 [] memory participationAmounts 69 | ) 70 | external 71 | onlyAdmin 72 | { 73 | for(uint i = 0; i < participants.length; i++) { 74 | registerParticipant(participants[i], participationAmounts[i]); 75 | } 76 | } 77 | 78 | 79 | /// Register participant 80 | function registerParticipant( 81 | address participant, 82 | uint participationAmount 83 | ) 84 | internal 85 | { 86 | require(totalTokensToDistribute.sub(totalTokensWithdrawn).add(participationAmount) <= token.balanceOf(address(this)), 87 | "Safeguarding existing token buyers. Not enough tokens." 88 | ); 89 | 90 | totalTokensToDistribute = totalTokensToDistribute.add(participationAmount); 91 | 92 | require(!hasParticipated[participant], "User already registered as participant."); 93 | 94 | uint initialPortionAmount = participationAmount.mul(20).div(100); 95 | // Vested 80% 96 | uint vestedAmount = participationAmount.sub(initialPortionAmount); 97 | 98 | // Compute amount per portion 99 | uint portionAmount = vestedAmount.div(numberOfPortions); 100 | bool[] memory isPortionWithdrawn = new bool[](numberOfPortions); 101 | 102 | // Create new participation object 103 | Participation memory p = Participation({ 104 | initialPortion: initialPortionAmount, 105 | vestedAmount: vestedAmount, 106 | amountPerPortion: portionAmount, 107 | initialPortionWithdrawn: false, 108 | isVestedPortionWithdrawn: isPortionWithdrawn 109 | }); 110 | 111 | // Map user and his participation 112 | addressToParticipation[participant] = p; 113 | // Mark that user have participated 114 | hasParticipated[participant] = true; 115 | } 116 | 117 | 118 | // User will always withdraw everything available 119 | function withdraw() 120 | external 121 | { 122 | address user = msg.sender; 123 | require(hasParticipated[user] == true, "Withdraw: User is not a participant."); 124 | 125 | Participation storage p = addressToParticipation[user]; 126 | 127 | uint256 totalToWithdraw = 0; 128 | 129 | // Initial portion can be withdrawn 130 | if(!p.initialPortionWithdrawn && block.timestamp >= initialPortionUnlockingTime) { 131 | totalToWithdraw = totalToWithdraw.add(p.initialPortion); 132 | // Mark initial portion as withdrawn 133 | p.initialPortionWithdrawn = true; 134 | } 135 | 136 | 137 | // For loop instead of while 138 | for(uint i = 0 ; i < numberOfPortions ; i++) { 139 | if(isPortionUnlocked(i) == true && i < distributionDates.length) { 140 | if(!p.isVestedPortionWithdrawn[i]) { 141 | // Add this portion to withdraw amount 142 | totalToWithdraw = totalToWithdraw.add(p.amountPerPortion); 143 | 144 | // Mark portion as withdrawn 145 | p.isVestedPortionWithdrawn[i] = true; 146 | } 147 | } 148 | } 149 | 150 | // Account total tokens withdrawn. 151 | totalTokensWithdrawn = totalTokensWithdrawn.add(totalToWithdraw); 152 | // Transfer all tokens to user 153 | token.transfer(user, totalToWithdraw); 154 | } 155 | 156 | function isPortionUnlocked(uint portionId) 157 | public 158 | view 159 | returns (bool) 160 | { 161 | return block.timestamp >= distributionDates[portionId]; 162 | } 163 | 164 | 165 | function getParticipation(address account) 166 | external 167 | view 168 | returns (uint256, uint256, uint256, bool, bool [] memory) 169 | { 170 | Participation memory p = addressToParticipation[account]; 171 | bool [] memory isVestedPortionWithdrawn = new bool [](numberOfPortions); 172 | 173 | for(uint i=0; i < numberOfPortions; i++) { 174 | isVestedPortionWithdrawn[i] = p.isVestedPortionWithdrawn[i]; 175 | } 176 | 177 | return ( 178 | p.initialPortion, 179 | p.vestedAmount, 180 | p.amountPerPortion, 181 | p.initialPortionWithdrawn, 182 | isVestedPortionWithdrawn 183 | ); 184 | } 185 | 186 | // Get all distribution dates 187 | function getDistributionDates() 188 | external 189 | view 190 | returns (uint256 [] memory) 191 | { 192 | return distributionDates; 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /contracts/ParticipationVestingSeed.sol: -------------------------------------------------------------------------------- 1 | //"SPDX-License-Identifier: UNLICENSED" 2 | pragma solidity ^0.6.12; 3 | 4 | import "./math/SafeMath.sol"; 5 | import "./IERC20.sol"; 6 | 7 | /// ParticipationVesting smart contract 8 | contract ParticipationVestingSeed { 9 | 10 | using SafeMath for *; 11 | 12 | uint public totalTokensToDistribute; 13 | uint public totalTokensWithdrawn; 14 | 15 | struct Participation { 16 | uint256 initialPortion; 17 | uint256 vestedAmount; 18 | uint256 amountPerPortion; 19 | bool initialPortionWithdrawn; 20 | bool [] isVestedPortionWithdrawn; 21 | } 22 | 23 | IERC20 public token; 24 | 25 | address public adminWallet; 26 | mapping(address => Participation) public addressToParticipation; 27 | mapping(address => bool) public hasParticipated; 28 | 29 | uint public initialPortionUnlockingTime; 30 | uint public numberOfPortions; 31 | uint [] distributionDates; 32 | 33 | modifier onlyAdmin { 34 | require(msg.sender == adminWallet, "OnlyAdmin: Restricted access."); 35 | _; 36 | } 37 | 38 | /// Load initial distribution dates 39 | constructor ( 40 | uint _numberOfPortions, 41 | uint timeBetweenPortions, 42 | uint distributionStartDate, 43 | uint _initialPortionUnlockingTime, 44 | address _adminWallet, 45 | address _token 46 | ) 47 | public 48 | { 49 | // Set admin wallet 50 | adminWallet = _adminWallet; 51 | // Store number of portions 52 | numberOfPortions = _numberOfPortions; 53 | 54 | // Time when initial portion is unlocked 55 | initialPortionUnlockingTime = _initialPortionUnlockingTime; 56 | 57 | // Set distribution dates 58 | for(uint i = 0 ; i < _numberOfPortions; i++) { 59 | distributionDates.push(distributionStartDate + i*timeBetweenPortions); 60 | } 61 | // Set the token address 62 | token = IERC20(_token); 63 | } 64 | 65 | // Function to register multiple participants at a time 66 | function registerParticipants( 67 | address [] memory participants, 68 | uint256 [] memory participationAmounts 69 | ) 70 | external 71 | onlyAdmin 72 | { 73 | for(uint i = 0; i < participants.length; i++) { 74 | registerParticipant(participants[i], participationAmounts[i]); 75 | } 76 | } 77 | 78 | 79 | /// Register participant 80 | function registerParticipant( 81 | address participant, 82 | uint participationAmount 83 | ) 84 | internal 85 | { 86 | require(totalTokensToDistribute.sub(totalTokensWithdrawn).add(participationAmount) <= token.balanceOf(address(this)), 87 | "Safeguarding existing token buyers. Not enough tokens." 88 | ); 89 | 90 | totalTokensToDistribute = totalTokensToDistribute.add(participationAmount); 91 | 92 | require(!hasParticipated[participant], "User already registered as participant."); 93 | 94 | uint initialPortionAmount = participationAmount.mul(10).div(100); 95 | // Vested 90% 96 | uint vestedAmount = participationAmount.sub(initialPortionAmount); 97 | 98 | // Compute amount per portion 99 | uint portionAmount = vestedAmount.div(numberOfPortions); 100 | bool[] memory isPortionWithdrawn = new bool[](numberOfPortions); 101 | 102 | // Create new participation object 103 | Participation memory p = Participation({ 104 | initialPortion: initialPortionAmount, 105 | vestedAmount: vestedAmount, 106 | amountPerPortion: portionAmount, 107 | initialPortionWithdrawn: false, 108 | isVestedPortionWithdrawn: isPortionWithdrawn 109 | }); 110 | 111 | // Map user and his participation 112 | addressToParticipation[participant] = p; 113 | // Mark that user have participated 114 | hasParticipated[participant] = true; 115 | } 116 | 117 | 118 | // User will always withdraw everything available 119 | function withdraw() 120 | external 121 | { 122 | address user = msg.sender; 123 | require(hasParticipated[user] == true, "Withdraw: User is not a participant."); 124 | 125 | Participation storage p = addressToParticipation[user]; 126 | 127 | uint256 totalToWithdraw = 0; 128 | 129 | // Initial portion can be withdrawn 130 | if(!p.initialPortionWithdrawn && block.timestamp >= initialPortionUnlockingTime) { 131 | totalToWithdraw = totalToWithdraw.add(p.initialPortion); 132 | // Mark initial portion as withdrawn 133 | p.initialPortionWithdrawn = true; 134 | } 135 | 136 | 137 | // For loop instead of while 138 | for(uint i = 0 ; i < numberOfPortions ; i++) { 139 | if(isPortionUnlocked(i) == true && i < distributionDates.length) { 140 | if(!p.isVestedPortionWithdrawn[i]) { 141 | // Add this portion to withdraw amount 142 | totalToWithdraw = totalToWithdraw.add(p.amountPerPortion); 143 | 144 | // Mark portion as withdrawn 145 | p.isVestedPortionWithdrawn[i] = true; 146 | } 147 | } 148 | } 149 | 150 | // Account total tokens withdrawn. 151 | totalTokensWithdrawn = totalTokensWithdrawn.add(totalToWithdraw); 152 | // Transfer all tokens to user 153 | token.transfer(user, totalToWithdraw); 154 | } 155 | 156 | function isPortionUnlocked(uint portionId) 157 | public 158 | view 159 | returns (bool) 160 | { 161 | return block.timestamp >= distributionDates[portionId]; 162 | } 163 | 164 | 165 | function getParticipation(address account) 166 | external 167 | view 168 | returns (uint256, uint256, uint256, bool, bool [] memory) 169 | { 170 | Participation memory p = addressToParticipation[account]; 171 | bool [] memory isVestedPortionWithdrawn = new bool [](numberOfPortions); 172 | 173 | for(uint i=0; i < numberOfPortions; i++) { 174 | isVestedPortionWithdrawn[i] = p.isVestedPortionWithdrawn[i]; 175 | } 176 | 177 | return ( 178 | p.initialPortion, 179 | p.vestedAmount, 180 | p.amountPerPortion, 181 | p.initialPortionWithdrawn, 182 | isVestedPortionWithdrawn 183 | ); 184 | } 185 | 186 | // Get all distribution dates 187 | function getDistributionDates() 188 | external 189 | view 190 | returns (uint256 [] memory) 191 | { 192 | return distributionDates; 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /contracts/XavaToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.6.12; 4 | 5 | import "./math/SafeMath.sol"; 6 | import "./utils/Context.sol"; 7 | import "./IERC20.sol"; 8 | 9 | contract XavaToken is Context, IERC20 { 10 | using SafeMath for uint256; 11 | 12 | mapping (address => uint256) private _balances; 13 | 14 | mapping (address => mapping (address => uint256)) private _allowances; 15 | 16 | uint256 private _totalSupply; 17 | 18 | string private _name; 19 | string private _symbol; 20 | uint8 private _decimals; 21 | 22 | constructor (string memory name_, string memory symbol_, uint256 totalSupply_, uint8 decimals_) public { 23 | _name = name_; 24 | _symbol = symbol_; 25 | _decimals = decimals_; 26 | _mint(_msgSender(), totalSupply_); 27 | } 28 | 29 | function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 30 | _transfer(_msgSender(), recipient, amount); 31 | return true; 32 | } 33 | 34 | function approve(address spender, uint256 amount) public virtual override returns (bool) { 35 | _approve(_msgSender(), spender, amount); 36 | return true; 37 | } 38 | 39 | function burn(uint amount) public virtual { 40 | _burn(_msgSender(), amount); 41 | } 42 | 43 | function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { 44 | _transfer(sender, recipient, amount); 45 | _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 46 | return true; 47 | } 48 | 49 | function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 50 | _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 51 | return true; 52 | } 53 | 54 | function _transfer(address sender, address recipient, uint256 amount) internal virtual { 55 | require(sender != address(0), "ERC20: transfer from the zero address"); 56 | require(recipient != address(0), "ERC20: transfer to the zero address"); 57 | 58 | 59 | _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 60 | _balances[recipient] = _balances[recipient].add(amount); 61 | emit Transfer(sender, recipient, amount); 62 | } 63 | 64 | function _mint(address account, uint256 amount) internal virtual { 65 | require(account != address(0), "ERC20: mint to the zero address"); 66 | 67 | _totalSupply = _totalSupply.add(amount); 68 | _balances[account] = _balances[account].add(amount); 69 | emit Transfer(address(0), account, amount); 70 | } 71 | 72 | function _burn(address account, uint256 amount) internal virtual { 73 | require(account != address(0), "ERC20: burn from the zero address"); 74 | 75 | _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 76 | _totalSupply = _totalSupply.sub(amount); 77 | emit Transfer(account, address(0), amount); 78 | } 79 | 80 | function _approve(address owner, address spender, uint256 amount) internal virtual { 81 | require(owner != address(0), "ERC20: approve from the zero address"); 82 | require(spender != address(0), "ERC20: approve to the zero address"); 83 | 84 | _allowances[owner][spender] = amount; 85 | emit Approval(owner, spender, amount); 86 | } 87 | 88 | function _setupDecimals(uint8 decimals_) internal virtual { 89 | _decimals = decimals_; 90 | } 91 | 92 | function name() public view virtual returns (string memory) { 93 | return _name; 94 | } 95 | 96 | function allowance(address owner, address spender) public view virtual override returns (uint256) { 97 | return _allowances[owner][spender]; 98 | } 99 | 100 | function symbol() public view virtual returns (string memory) { 101 | return _symbol; 102 | } 103 | 104 | function decimals() public view virtual returns (uint8) { 105 | return _decimals; 106 | } 107 | 108 | function totalSupply() public view virtual override returns (uint256) { 109 | return _totalSupply; 110 | } 111 | 112 | function balanceOf(address account) public view virtual override returns (uint256) { 113 | return _balances[account]; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /contracts/airdrop/Airdrop.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.12; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | import "@openzeppelin/contracts/cryptography/ECDSA.sol"; 5 | import "../interfaces/IAdmin.sol"; 6 | import "../math/SafeMath.sol"; 7 | 8 | contract Airdrop { 9 | 10 | using ECDSA for bytes32; 11 | using SafeMath for *; 12 | 13 | IERC20 public airdropToken; 14 | IAdmin public admin; 15 | uint256 public totalTokensWithdrawn; 16 | 17 | mapping (address => bool) public wasClaimed; 18 | 19 | event TokensAirdropped(address beneficiary, uint256 amount); 20 | 21 | // Constructor, initial setup 22 | constructor(address _airdropToken, address _admin) public { 23 | require(_admin != address(0)); 24 | require(_airdropToken != address(0)); 25 | 26 | admin = IAdmin(_admin); 27 | airdropToken = IERC20(_airdropToken); 28 | } 29 | 30 | // Function to withdraw tokens. 31 | function withdrawTokens(bytes memory signature, uint256 amount) public { 32 | require(msg.sender == tx.origin, "Require that message sender is tx-origin."); 33 | 34 | address beneficiary = msg.sender; 35 | 36 | require(checkSignature(signature, beneficiary, amount), "Not eligible to claim tokens!"); 37 | require(!wasClaimed[beneficiary], "Already claimed!"); 38 | wasClaimed[msg.sender] = true; 39 | 40 | bool status = airdropToken.transfer(beneficiary, amount); 41 | require(status, "Token transfer status is false."); 42 | 43 | totalTokensWithdrawn = totalTokensWithdrawn.add(amount); 44 | emit TokensAirdropped(beneficiary, amount); 45 | } 46 | 47 | // Get who signed the message based on the params 48 | function getSigner(bytes memory signature, address beneficiary, uint256 amount) public view returns (address) { 49 | bytes32 hash = keccak256(abi.encodePacked(beneficiary, amount, address(this))); 50 | bytes32 messageHash = hash.toEthSignedMessageHash(); 51 | return messageHash.recover(signature); 52 | } 53 | 54 | // Check that signature is valid, and is signed by Admin wallets 55 | function checkSignature(bytes memory signature, address beneficiary, uint256 amount) public view returns (bool) { 56 | return admin.isAdmin(getSigner(signature, beneficiary, amount)); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /contracts/airdrop/AirdropAVAX.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.12; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | import "@openzeppelin/contracts/cryptography/ECDSA.sol"; 5 | import "../interfaces/IAdmin.sol"; 6 | import "../math/SafeMath.sol"; 7 | 8 | contract AirdropAVAX { 9 | 10 | using ECDSA for bytes32; 11 | using SafeMath for *; 12 | 13 | IAdmin public admin; 14 | uint256 public totalTokensWithdrawn; 15 | 16 | mapping (address => bool) public wasClaimed; 17 | 18 | event SentAVAX(address beneficiary, uint256 amount); 19 | 20 | // Constructor, initial setup 21 | constructor(address _admin) public { 22 | require(_admin != address(0)); 23 | admin = IAdmin(_admin); 24 | } 25 | 26 | // Safe transfer AVAX to users 27 | function safeTransferAVAX(address to, uint256 value) internal { 28 | // Safely transfer AVAX to address 29 | (bool success, ) = to.call{value: value}(new bytes(0)); 30 | // Require that transfer was successful. 31 | require(success, "AVAX transfer failed."); 32 | } 33 | 34 | // Function to withdraw tokens. 35 | function withdrawTokens(bytes memory signature, uint256 amount) public { 36 | // Allow only direct - not contract calls. 37 | require(msg.sender == tx.origin, "Require that message sender is tx-origin."); 38 | // Get beneficiary address 39 | address beneficiary = msg.sender; 40 | // Verify signature 41 | require(checkSignature(signature, beneficiary, amount), "Not eligible to claim AVAX!"); 42 | // Make sure user didn't claim 43 | require(!wasClaimed[beneficiary], "Already claimed AVAX!"); 44 | // Mark that user already claimed. 45 | wasClaimed[msg.sender] = true; 46 | // Transfer AVAX to user 47 | safeTransferAVAX(beneficiary, amount); 48 | // Increase amount of AVAX withdrawn 49 | totalTokensWithdrawn = totalTokensWithdrawn.add(amount); 50 | // Trigger event that AVAX is sent. 51 | emit SentAVAX(beneficiary, amount); 52 | } 53 | 54 | // Get who signed the message based on the params 55 | function getSigner(bytes memory signature, address beneficiary, uint256 amount) public view returns (address) { 56 | bytes32 hash = keccak256(abi.encodePacked(beneficiary, amount, address(this))); 57 | bytes32 messageHash = hash.toEthSignedMessageHash(); 58 | return messageHash.recover(signature); 59 | } 60 | 61 | // Check that signature is valid, and is signed by Admin wallets 62 | function checkSignature(bytes memory signature, address beneficiary, uint256 amount) public view returns (bool) { 63 | return admin.isAdmin(getSigner(signature, beneficiary, amount)); 64 | } 65 | 66 | receive() external payable {} 67 | } 68 | -------------------------------------------------------------------------------- /contracts/airdrop/AirdropSale.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: UNLICENSED 2 | pragma solidity 0.6.12; 3 | 4 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 5 | import "@openzeppelin/contracts/cryptography/ECDSA.sol"; 6 | import "../interfaces/IAdmin.sol"; 7 | import "../math/SafeMath.sol"; 8 | 9 | contract AirdropSale { 10 | 11 | using ECDSA for bytes32; 12 | using SafeMath for uint256; 13 | 14 | // Globals 15 | IAdmin public immutable admin; 16 | address[] public airdropERC20s; 17 | bool public includesAVAX; 18 | bool public includesERC20s; 19 | mapping (address => uint256) public tokenToTotalWithdrawn; 20 | mapping (address => bool) public wasClaimed; 21 | 22 | // Events 23 | event SentERC20(address beneficiary, address token, uint256 amount); 24 | event SentAVAX(address beneficiary, uint256 amount); 25 | 26 | // Constructor, initial setup 27 | constructor(address[] memory _airdropERC20s, address _admin, bool _includesAVAX) public { 28 | require(_admin != address(0)); 29 | admin = IAdmin(_admin); 30 | 31 | // Mark if contract airdrops AVAX 32 | if(_includesAVAX) {includesAVAX = true;} 33 | 34 | // Add airdrop tokens to array 35 | if(_airdropERC20s.length != 0) { 36 | includesERC20s = true; 37 | for(uint i = 0; i < _airdropERC20s.length; i++) { 38 | require(_airdropERC20s[i] != address(0)); 39 | airdropERC20s.push(_airdropERC20s[i]); 40 | } 41 | } 42 | // else: leave includesERC20 on false/default 43 | } 44 | 45 | /// @notice Function to withdraw tokens 46 | function withdrawTokens( 47 | bytes calldata signature, 48 | uint256[] calldata amounts 49 | ) external { 50 | // Allow only direct call 51 | require(msg.sender == tx.origin, "Require that message sender is tx-origin."); 52 | // Require that array sizes are matching 53 | if(includesAVAX) { 54 | require(airdropERC20s.length.add(1) == amounts.length, "Array size mismatch."); 55 | } else { 56 | require(airdropERC20s.length == amounts.length, "Array size mismatch."); 57 | } 58 | 59 | // Get beneficiary address 60 | address beneficiary = msg.sender; 61 | 62 | // Hash amounts array to get a compact and unique value for signing 63 | bytes32 hashedAmounts = keccak256(abi.encodePacked(amounts)); 64 | // Validate signature 65 | require(checkSignature(signature, beneficiary, hashedAmounts), "Not eligible to claim tokens!"); 66 | // Require that user didn't claim already 67 | require(!wasClaimed[beneficiary], "Already claimed!"); 68 | // Mark that user claimed 69 | wasClaimed[beneficiary] = true; 70 | 71 | // Amounts array's ERC20 distribution starting index 72 | uint startIndex = 0; 73 | 74 | // Only if airdrop includes AVAX 75 | if(includesAVAX) { 76 | // Perform AVAX safeTransferAVAX 77 | safeTransferAVAX(beneficiary, amounts[0]); 78 | // Switch startIndex to 1 if airdropping AVAX 79 | startIndex = 1; 80 | } 81 | 82 | // Only if airdrop includes ERC20s 83 | if(includesERC20s) { 84 | // Go through all of the airdrop tokens 85 | for(uint i = startIndex; i < amounts.length; i++) { 86 | // Allows to skip token transfers for user's on order 87 | if(amounts[i] > 0) { 88 | // Compute airdropERC20s proper index 89 | uint j = i.sub(startIndex); 90 | // Perform transfer 91 | bool status = IERC20(airdropERC20s[j]).transfer(beneficiary, amounts[i]); 92 | // Require that transfer was successful 93 | require(status, "Token transfer status is false."); 94 | // Increase token's withdrawn amount 95 | tokenToTotalWithdrawn[airdropERC20s[j]] = tokenToTotalWithdrawn[airdropERC20s[j]].add(amounts[i]); 96 | // Trigger event that token is sent 97 | emit SentERC20(beneficiary,airdropERC20s[j], amounts[i]); 98 | } 99 | } 100 | } 101 | } 102 | 103 | // Get who signed the message based on the params 104 | function getSigner(bytes memory signature, address beneficiary, bytes32 hashedAmounts) public view returns (address) { 105 | bytes32 hash = keccak256(abi.encode(beneficiary, hashedAmounts, address(this))); 106 | bytes32 messageHash = hash.toEthSignedMessageHash(); 107 | return messageHash.recover(signature); 108 | } 109 | 110 | // Check that signature is valid, and is signed by Admin wallets 111 | function checkSignature(bytes memory signature, address beneficiary, bytes32 hashedAmounts) public view returns (bool) { 112 | return admin.isAdmin(getSigner(signature, beneficiary, hashedAmounts)); 113 | } 114 | 115 | // Safe transfer AVAX to users 116 | function safeTransferAVAX(address to, uint256 value) internal { 117 | // Safely transfer AVAX to address 118 | (bool success, ) = to.call{value: value}(new bytes(0)); 119 | // Require that transfer was successful. 120 | require(success, "AVAX transfer failed."); 121 | // Trigger relevant event 122 | emit SentAVAX(to, value); 123 | } 124 | 125 | // Enable receiving AVAX 126 | receive() external payable {} 127 | } 128 | -------------------------------------------------------------------------------- /contracts/farming/DevToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.6.12; 4 | 5 | import "../utils/Context.sol"; 6 | import "../IERC20.sol"; 7 | import "../math/SafeMath.sol"; 8 | 9 | 10 | contract DevToken is Context, IERC20 { 11 | using SafeMath for uint256; 12 | 13 | mapping (address => uint256) private _balances; 14 | 15 | mapping (address => mapping (address => uint256)) private _allowances; 16 | 17 | uint256 private _totalSupply; 18 | 19 | string private _name; 20 | string private _symbol; 21 | uint8 private _decimals; 22 | 23 | constructor (string memory name_, string memory symbol_, uint256 totalSupply_, uint8 decimals_) public { 24 | _name = name_; 25 | _symbol = symbol_; 26 | _decimals = decimals_; 27 | _mint(_msgSender(), totalSupply_); 28 | } 29 | 30 | function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 31 | _transfer(_msgSender(), recipient, amount); 32 | return true; 33 | } 34 | 35 | function approve(address spender, uint256 amount) public virtual override returns (bool) { 36 | _approve(_msgSender(), spender, amount); 37 | return true; 38 | } 39 | 40 | function burn(uint amount) public virtual { 41 | _burn(_msgSender(), amount); 42 | } 43 | 44 | function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { 45 | _transfer(sender, recipient, amount); 46 | _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 47 | return true; 48 | } 49 | 50 | function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 51 | _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 52 | return true; 53 | } 54 | 55 | function _transfer(address sender, address recipient, uint256 amount) internal virtual { 56 | require(sender != address(0), "ERC20: transfer from the zero address"); 57 | require(recipient != address(0), "ERC20: transfer to the zero address"); 58 | 59 | 60 | _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 61 | _balances[recipient] = _balances[recipient].add(amount); 62 | emit Transfer(sender, recipient, amount); 63 | } 64 | 65 | function _mint(address account, uint256 amount) internal virtual { 66 | require(account != address(0), "ERC20: mint to the zero address"); 67 | 68 | _totalSupply = _totalSupply.add(amount); 69 | _balances[account] = _balances[account].add(amount); 70 | emit Transfer(address(0), account, amount); 71 | } 72 | 73 | function _burn(address account, uint256 amount) internal virtual { 74 | require(account != address(0), "ERC20: burn from the zero address"); 75 | 76 | _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 77 | _totalSupply = _totalSupply.sub(amount); 78 | emit Transfer(account, address(0), amount); 79 | } 80 | 81 | function _approve(address owner, address spender, uint256 amount) internal virtual { 82 | require(owner != address(0), "ERC20: approve from the zero address"); 83 | require(spender != address(0), "ERC20: approve to the zero address"); 84 | 85 | _allowances[owner][spender] = amount; 86 | emit Approval(owner, spender, amount); 87 | } 88 | 89 | function _setupDecimals(uint8 decimals_) internal virtual { 90 | _decimals = decimals_; 91 | } 92 | 93 | function name() public view virtual returns (string memory) { 94 | return _name; 95 | } 96 | 97 | function allowance(address owner, address spender) public view virtual override returns (uint256) { 98 | return _allowances[owner][spender]; 99 | } 100 | 101 | function symbol() public view virtual returns (string memory) { 102 | return _symbol; 103 | } 104 | 105 | function decimals() public view virtual returns (uint8) { 106 | return _decimals; 107 | } 108 | 109 | function totalSupply() public view virtual override returns (uint256) { 110 | return _totalSupply; 111 | } 112 | 113 | function balanceOf(address account) public view virtual override returns (uint256) { 114 | return _balances[account]; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /contracts/interfaces/IAdmin.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: UNLICENSED 2 | pragma solidity 0.6.12; 3 | 4 | interface IAdmin { 5 | function isAdmin(address user) external view returns (bool); 6 | } 7 | -------------------------------------------------------------------------------- /contracts/interfaces/IAllocationStaking.sol: -------------------------------------------------------------------------------- 1 | //"SPDX-License-Identifier: UNLICENSED" 2 | pragma solidity 0.6.12; 3 | 4 | interface IAllocationStaking { 5 | function redistributeXava(uint256 _pid, address _user, uint256 _amountToBurn) external; 6 | function deposited(uint256 _pid, address _user) external view returns (uint256); 7 | function setTokensUnlockTime(uint256 _pid, address _user, uint256 _tokensUnlockTime) external; 8 | } 9 | -------------------------------------------------------------------------------- /contracts/interfaces/IAvalaunchMarketplace.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.6.12; 3 | 4 | interface IAvalaunchMarketplace { 5 | function listPortions(address owner, uint256[] calldata portions) external; 6 | function removePortions(address owner, uint256[] calldata portions) external; 7 | function approveSale(address sale) external; 8 | } -------------------------------------------------------------------------------- /contracts/interfaces/IAvalaunchSale.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.6.12; 3 | 4 | /** 5 | * IAvalaunchSale contract. 6 | * Date created: 3.3.22. 7 | */ 8 | interface IAvalaunchSale { 9 | function autoParticipate( 10 | address user, 11 | uint256 amount, 12 | uint256 amountXavaToBurn, 13 | uint256 roundId 14 | ) external payable; 15 | 16 | function boostParticipation( 17 | address user, 18 | uint256 amountXavaToBurn 19 | ) 20 | external payable; 21 | } 22 | -------------------------------------------------------------------------------- /contracts/interfaces/IAvalaunchSaleV2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.6.12; 3 | 4 | interface IAvalaunchSaleV2 { 5 | function transferPortions(address seller, address buyer, uint256[] calldata portions) external; 6 | function numberOfVestedPortions() external view returns (uint256); 7 | } 8 | -------------------------------------------------------------------------------- /contracts/interfaces/ICollateral.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.6.12; 3 | 4 | interface ICollateral { 5 | function depositCollateral() external payable; 6 | function withdrawCollateral() external payable; 7 | function totalBalance() external view returns (uint256); 8 | } -------------------------------------------------------------------------------- /contracts/interfaces/IDexalotPortfolio.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.6.12; 3 | 4 | /** 5 | * IDexalotPortfolio contract. 6 | * Date created: 28.1.22. 7 | */ 8 | interface IDexalotPortfolio { 9 | function depositTokenFromContract(address _from, bytes32 _symbol, uint _quantity) external; 10 | } 11 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC20Metadata.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.6.12; 4 | 5 | /** 6 | * @dev Interface for the optional metadata functions from the ERC20 standard. 7 | */ 8 | interface IERC20Metadata { 9 | /** 10 | * @dev Returns the name of the token. 11 | */ 12 | function name() external view returns (string memory); 13 | 14 | /** 15 | * @dev Returns the symbol of the token. 16 | */ 17 | function symbol() external view returns (string memory); 18 | 19 | /** 20 | * @dev Returns the decimals places of the token. 21 | */ 22 | function decimals() external view returns (uint8); 23 | } 24 | -------------------------------------------------------------------------------- /contracts/interfaces/ISalesFactory.sol: -------------------------------------------------------------------------------- 1 | // "SPDX-License-Identifier: UNLICENSED" 2 | pragma solidity 0.6.12; 3 | 4 | interface ISalesFactory { 5 | function isSaleCreatedThroughFactory(address sale) external view returns (bool); 6 | } 7 | -------------------------------------------------------------------------------- /contracts/math/SafeMath.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity >=0.6.0 <0.8.0; 4 | 5 | /** 6 | * @dev Wrappers over Solidity's arithmetic operations with added overflow 7 | * checks. 8 | * 9 | * Arithmetic operations in Solidity wrap on overflow. This can easily result 10 | * in bugs, because programmers usually assume that an overflow raises an 11 | * error, which is the standard behavior in high level programming languages. 12 | * `SafeMath` restores this intuition by reverting the transaction when an 13 | * operation overflows. 14 | * 15 | * Using this library instead of the unchecked operations eliminates an entire 16 | * class of bugs, so it's recommended to use it always. 17 | */ 18 | library SafeMath { 19 | /** 20 | * @dev Returns the addition of two unsigned integers, with an overflow flag. 21 | * 22 | * _Available since v3.4._ 23 | */ 24 | function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { 25 | uint256 c = a + b; 26 | if (c < a) return (false, 0); 27 | return (true, c); 28 | } 29 | 30 | /** 31 | * @dev Returns the substraction of two unsigned integers, with an overflow flag. 32 | * 33 | * _Available since v3.4._ 34 | */ 35 | function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { 36 | if (b > a) return (false, 0); 37 | return (true, a - b); 38 | } 39 | 40 | /** 41 | * @dev Returns the multiplication of two unsigned integers, with an overflow flag. 42 | * 43 | * _Available since v3.4._ 44 | */ 45 | function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { 46 | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 47 | // benefit is lost if 'b' is also tested. 48 | // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 49 | if (a == 0) return (true, 0); 50 | uint256 c = a * b; 51 | if (c / a != b) return (false, 0); 52 | return (true, c); 53 | } 54 | 55 | /** 56 | * @dev Returns the division of two unsigned integers, with a division by zero flag. 57 | * 58 | * _Available since v3.4._ 59 | */ 60 | function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { 61 | if (b == 0) return (false, 0); 62 | return (true, a / b); 63 | } 64 | 65 | /** 66 | * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. 67 | * 68 | * _Available since v3.4._ 69 | */ 70 | function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { 71 | if (b == 0) return (false, 0); 72 | return (true, a % b); 73 | } 74 | 75 | /** 76 | * @dev Returns the addition of two unsigned integers, reverting on 77 | * overflow. 78 | * 79 | * Counterpart to Solidity's `+` operator. 80 | * 81 | * Requirements: 82 | * 83 | * - Addition cannot overflow. 84 | */ 85 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 86 | uint256 c = a + b; 87 | require(c >= a, "SafeMath: addition overflow"); 88 | return c; 89 | } 90 | 91 | /** 92 | * @dev Returns the subtraction of two unsigned integers, reverting on 93 | * overflow (when the result is negative). 94 | * 95 | * Counterpart to Solidity's `-` operator. 96 | * 97 | * Requirements: 98 | * 99 | * - Subtraction cannot overflow. 100 | */ 101 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 102 | require(b <= a, "SafeMath: subtraction overflow"); 103 | return a - b; 104 | } 105 | 106 | /** 107 | * @dev Returns the multiplication of two unsigned integers, reverting on 108 | * overflow. 109 | * 110 | * Counterpart to Solidity's `*` operator. 111 | * 112 | * Requirements: 113 | * 114 | * - Multiplication cannot overflow. 115 | */ 116 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 117 | if (a == 0) return 0; 118 | uint256 c = a * b; 119 | require(c / a == b, "SafeMath: multiplication overflow"); 120 | return c; 121 | } 122 | 123 | /** 124 | * @dev Returns the integer division of two unsigned integers, reverting on 125 | * division by zero. The result is rounded towards zero. 126 | * 127 | * Counterpart to Solidity's `/` operator. Note: this function uses a 128 | * `revert` opcode (which leaves remaining gas untouched) while Solidity 129 | * uses an invalid opcode to revert (consuming all remaining gas). 130 | * 131 | * Requirements: 132 | * 133 | * - The divisor cannot be zero. 134 | */ 135 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 136 | require(b > 0, "SafeMath: division by zero"); 137 | return a / b; 138 | } 139 | 140 | /** 141 | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 142 | * reverting when dividing by zero. 143 | * 144 | * Counterpart to Solidity's `%` operator. This function uses a `revert` 145 | * opcode (which leaves remaining gas untouched) while Solidity uses an 146 | * invalid opcode to revert (consuming all remaining gas). 147 | * 148 | * Requirements: 149 | * 150 | * - The divisor cannot be zero. 151 | */ 152 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 153 | require(b > 0, "SafeMath: modulo by zero"); 154 | return a % b; 155 | } 156 | 157 | /** 158 | * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 159 | * overflow (when the result is negative). 160 | * 161 | * CAUTION: This function is deprecated because it requires allocating memory for the error 162 | * message unnecessarily. For custom revert reasons use {trySub}. 163 | * 164 | * Counterpart to Solidity's `-` operator. 165 | * 166 | * Requirements: 167 | * 168 | * - Subtraction cannot overflow. 169 | */ 170 | function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 171 | require(b <= a, errorMessage); 172 | return a - b; 173 | } 174 | 175 | /** 176 | * @dev Returns the integer division of two unsigned integers, reverting with custom message on 177 | * division by zero. The result is rounded towards zero. 178 | * 179 | * CAUTION: This function is deprecated because it requires allocating memory for the error 180 | * message unnecessarily. For custom revert reasons use {tryDiv}. 181 | * 182 | * Counterpart to Solidity's `/` operator. Note: this function uses a 183 | * `revert` opcode (which leaves remaining gas untouched) while Solidity 184 | * uses an invalid opcode to revert (consuming all remaining gas). 185 | * 186 | * Requirements: 187 | * 188 | * - The divisor cannot be zero. 189 | */ 190 | function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 191 | require(b > 0, errorMessage); 192 | return a / b; 193 | } 194 | 195 | /** 196 | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 197 | * reverting with custom message when dividing by zero. 198 | * 199 | * CAUTION: This function is deprecated because it requires allocating memory for the error 200 | * message unnecessarily. For custom revert reasons use {tryMod}. 201 | * 202 | * Counterpart to Solidity's `%` operator. This function uses a `revert` 203 | * opcode (which leaves remaining gas untouched) while Solidity uses an 204 | * invalid opcode to revert (consuming all remaining gas). 205 | * 206 | * Requirements: 207 | * 208 | * - The divisor cannot be zero. 209 | */ 210 | function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 211 | require(b > 0, errorMessage); 212 | return a % b; 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /contracts/sales/SalesFactory.sol: -------------------------------------------------------------------------------- 1 | // "SPDX-License-Identifier: UNLICENSED" 2 | pragma solidity 0.6.12; 3 | 4 | import "../interfaces/IAdmin.sol"; 5 | import "../interfaces/IAvalaunchMarketplace.sol"; 6 | 7 | contract SalesFactory { 8 | 9 | // Admin contract 10 | IAdmin public immutable admin; 11 | // Marketplace contract address 12 | IAvalaunchMarketplace public marketplace; 13 | // Allocation staking contract address 14 | address public allocationStaking; 15 | // Collateral contract address 16 | address public immutable collateral; 17 | // Moderator wallet address 18 | address public moderator; 19 | // Official sale creation flag 20 | mapping (address => bool) public isSaleCreatedThroughFactory; 21 | // Expose so query can be possible only by position as well 22 | address [] public allSales; 23 | // Latest sale implementation contract address 24 | address public implementation; 25 | 26 | // Events 27 | event SaleDeployed(address saleContract); 28 | event ImplementationSet(address implementation); 29 | event ModeratorSet(address moderator); 30 | event AllocationStakingSet(address moderator); 31 | event MarketplaceSet(address moderator); 32 | 33 | // Restricting calls only to sale admin 34 | modifier onlyAdmin { 35 | require(admin.isAdmin(msg.sender), "Only admin."); 36 | _; 37 | } 38 | 39 | constructor( 40 | address _adminContract, 41 | address _allocationStaking, 42 | address _collateral, 43 | address _marketplace, 44 | address _moderator 45 | ) public { 46 | require(_adminContract != address(0), "IE1"); 47 | require(_collateral != address(0), "IE2"); 48 | require(_moderator != address(0), "IE3"); 49 | 50 | admin = IAdmin(_adminContract); 51 | marketplace = IAvalaunchMarketplace(_marketplace); 52 | allocationStaking = _allocationStaking; 53 | collateral = _collateral; 54 | moderator = _moderator; 55 | } 56 | 57 | /// @notice Set moderator address 58 | function setModerator(address _moderator) external onlyAdmin { 59 | require(_moderator != address(0), "SE1"); 60 | moderator = _moderator; 61 | emit ModeratorSet(_moderator); 62 | } 63 | 64 | /// @notice Set allocation staking contract address 65 | function setAllocationStaking(address _allocationStaking) external onlyAdmin { 66 | require(_allocationStaking != address(0), "SE2"); 67 | allocationStaking = _allocationStaking; 68 | emit AllocationStakingSet(_allocationStaking); 69 | } 70 | 71 | /// @notice Set official marketplace contract 72 | function setAvalaunchMarketplace(address _marketplace) external onlyAdmin { 73 | require(_marketplace != address(0), "SE3"); 74 | marketplace = IAvalaunchMarketplace(_marketplace); 75 | emit MarketplaceSet(_marketplace); 76 | } 77 | 78 | /// @notice Function to set the latest sale implementation contract 79 | function setImplementation(address _implementation) external onlyAdmin { 80 | // Require that implementation is different from current one 81 | require( 82 | _implementation != implementation, 83 | "Given implementation is same as current." 84 | ); 85 | // Set new implementation 86 | implementation = _implementation; 87 | // Emit relevant event 88 | emit ImplementationSet(implementation); 89 | } 90 | 91 | /// @notice Admin function to deploy a new sale 92 | function deploySale() external onlyAdmin { 93 | // Require that implementation is set 94 | require(implementation != address(0), "Sale implementation not set."); 95 | 96 | // Deploy sale clone 97 | address sale; 98 | // Inline assembly works only with local vars 99 | address imp = implementation; 100 | 101 | /// @solidity memory-safe-assembly 102 | assembly { 103 | // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes 104 | // of the `implementation` address with the bytecode before the address. 105 | mstore(0x00, or(shr(0xe8, shl(0x60, imp)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000)) 106 | // Packs the remaining 17 bytes of `implementation` with the bytecode after the address. 107 | mstore(0x20, or(shl(0x78, imp), 0x5af43d82803e903d91602b57fd5bf3)) 108 | sale := create(0, 0x09, 0x37) 109 | } 110 | // Require that sale was created 111 | require(sale != address(0), "Sale creation failed."); 112 | 113 | // Mark sale as created through official factory 114 | isSaleCreatedThroughFactory[sale] = true; 115 | // Add sale to allSales 116 | allSales.push(sale); 117 | 118 | // Initialize sale 119 | (bool success, ) = sale.call( 120 | abi.encodeWithSignature( 121 | "initialize(address,address,address,address,address)", 122 | address(admin), allocationStaking, collateral, address(marketplace), moderator 123 | ) 124 | ); 125 | require(success, "Initialization failed."); 126 | 127 | // Approve sale on marketplace 128 | marketplace.approveSale(sale); 129 | 130 | // Emit relevant event 131 | emit SaleDeployed(sale); 132 | } 133 | 134 | /// @notice Function to return number of pools deployed 135 | function getNumberOfSalesDeployed() external view returns (uint) { 136 | return allSales.length; 137 | } 138 | 139 | /// @notice Get most recently deployed sale 140 | function getLastDeployedSale() external view returns (address) { 141 | if(allSales.length > 0) return allSales[allSales.length - 1]; 142 | // Return zero address if no sales were deployed 143 | return address(0); 144 | } 145 | 146 | /// @notice Function to get all sales between indexes 147 | function getAllSales(uint startIndex, uint endIndex) external view returns (address[] memory) { 148 | // Require valid index input 149 | require(endIndex >= startIndex && endIndex < allSales.length, "Invalid index range."); 150 | // Create new array for sale addresses 151 | address[] memory sales = new address[](endIndex - startIndex + 1); 152 | uint index = 0; 153 | // Fill the array with sale addresses 154 | for(uint i = startIndex; i <= endIndex; i++) { 155 | sales[index] = allSales[i]; 156 | index++; 157 | } 158 | return sales; 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /contracts/utils/Context.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.6.12; 4 | 5 | /* 6 | * @dev Provides information about the current execution context, including the 7 | * sender of the transaction and its data. While these are generally available 8 | * via msg.sender and msg.data, they should not be accessed in such a direct 9 | * manner, since when dealing with GSN meta-transactions the account sending and 10 | * paying for execution may not be the actual sender (as far as an application 11 | * is concerned). 12 | * 13 | * This contract is only required for intermediate, library-like contracts. 14 | */ 15 | abstract contract Context { 16 | function _msgSender() internal view virtual returns (address payable) { 17 | return msg.sender; 18 | } 19 | 20 | function _msgData() internal view virtual returns (bytes memory) { 21 | this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 22 | return msg.data; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /deployments/proxy-abis.json: -------------------------------------------------------------------------------- 1 | { 2 | "ProxyAdmin": [ 3 | { 4 | "anonymous": false, 5 | "inputs": [ 6 | { 7 | "indexed": true, 8 | "internalType": "address", 9 | "name": "previousOwner", 10 | "type": "address" 11 | }, 12 | { 13 | "indexed": true, 14 | "internalType": "address", 15 | "name": "newOwner", 16 | "type": "address" 17 | } 18 | ], 19 | "name": "OwnershipTransferred", 20 | "type": "event" 21 | }, 22 | { 23 | "inputs": [ 24 | { 25 | "internalType": "contract TransparentUpgradeableProxy", 26 | "name": "proxy", 27 | "type": "address" 28 | }, 29 | { 30 | "internalType": "address", 31 | "name": "newAdmin", 32 | "type": "address" 33 | } 34 | ], 35 | "name": "changeProxyAdmin", 36 | "outputs": [], 37 | "stateMutability": "nonpayable", 38 | "type": "function" 39 | }, 40 | { 41 | "inputs": [ 42 | { 43 | "internalType": "contract TransparentUpgradeableProxy", 44 | "name": "proxy", 45 | "type": "address" 46 | } 47 | ], 48 | "name": "getProxyAdmin", 49 | "outputs": [ 50 | { 51 | "internalType": "address", 52 | "name": "", 53 | "type": "address" 54 | } 55 | ], 56 | "stateMutability": "view", 57 | "type": "function" 58 | }, 59 | { 60 | "inputs": [ 61 | { 62 | "internalType": "contract TransparentUpgradeableProxy", 63 | "name": "proxy", 64 | "type": "address" 65 | } 66 | ], 67 | "name": "getProxyImplementation", 68 | "outputs": [ 69 | { 70 | "internalType": "address", 71 | "name": "", 72 | "type": "address" 73 | } 74 | ], 75 | "stateMutability": "view", 76 | "type": "function" 77 | }, 78 | { 79 | "inputs": [], 80 | "name": "owner", 81 | "outputs": [ 82 | { 83 | "internalType": "address", 84 | "name": "", 85 | "type": "address" 86 | } 87 | ], 88 | "stateMutability": "view", 89 | "type": "function" 90 | }, 91 | { 92 | "inputs": [], 93 | "name": "renounceOwnership", 94 | "outputs": [], 95 | "stateMutability": "nonpayable", 96 | "type": "function" 97 | }, 98 | { 99 | "inputs": [ 100 | { 101 | "internalType": "address", 102 | "name": "newOwner", 103 | "type": "address" 104 | } 105 | ], 106 | "name": "transferOwnership", 107 | "outputs": [], 108 | "stateMutability": "nonpayable", 109 | "type": "function" 110 | }, 111 | { 112 | "inputs": [ 113 | { 114 | "internalType": "contract TransparentUpgradeableProxy", 115 | "name": "proxy", 116 | "type": "address" 117 | }, 118 | { 119 | "internalType": "address", 120 | "name": "implementation", 121 | "type": "address" 122 | } 123 | ], 124 | "name": "upgrade", 125 | "outputs": [], 126 | "stateMutability": "nonpayable", 127 | "type": "function" 128 | }, 129 | { 130 | "inputs": [ 131 | { 132 | "internalType": "contract TransparentUpgradeableProxy", 133 | "name": "proxy", 134 | "type": "address" 135 | }, 136 | { 137 | "internalType": "address", 138 | "name": "implementation", 139 | "type": "address" 140 | }, 141 | { 142 | "internalType": "bytes", 143 | "name": "data", 144 | "type": "bytes" 145 | } 146 | ], 147 | "name": "upgradeAndCall", 148 | "outputs": [], 149 | "stateMutability": "payable", 150 | "type": "function" 151 | } 152 | ] 153 | } 154 | -------------------------------------------------------------------------------- /hardhat.config.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | require('@nomiclabs/hardhat-waffle') 3 | require('@nomiclabs/hardhat-ethers') 4 | require("@nomiclabs/hardhat-web3") 5 | require('@openzeppelin/hardhat-upgrades') 6 | require('solidity-coverage'); 7 | require('hardhat-gas-reporter'); 8 | require('hardhat-contract-sizer'); 9 | 10 | // This is a sample Hardhat task. To learn how to create your own go to 11 | // https://hardhat.org/guides/create-task.html 12 | task("accounts", "Prints the list of accounts", async () => { 13 | const accounts = await ethers.getSigners(); 14 | 15 | for (const account of accounts) { 16 | console.log(account.address); 17 | } 18 | }); 19 | 20 | const testPK = "0x56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027"; 21 | 22 | /** 23 | * @type import('hardhat/config').HardhatUserConfig 24 | */ 25 | module.exports = { 26 | defaultNetwork: 'avash', 27 | networks: { 28 | avash: { 29 | url: 'http://localhost:9650/ext/bc/C/rpc', 30 | gasPrice: 225000000000, 31 | chainId: 43112, 32 | accounts: [ 33 | "0x56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027", 34 | "0x7b4198529994b0dc604278c99d153cfd069d594753d471171a1d102a10438e07", 35 | "0x15614556be13730e9e8d6eacc1603143e7b96987429df8726384c2ec4502ef6e", 36 | "0x31b571bf6894a248831ff937bb49f7754509fe93bbd2517c9c73c4144c0e97dc", 37 | "0x6934bef917e01692b789da754a0eae31a8536eb465e7bff752ea291dad88c675", 38 | "0xe700bdbdbc279b808b1ec45f8c2370e4616d3a02c336e68d85d4668e08f53cff", 39 | "0xbbc2865b76ba28016bc2255c7504d000e046ae01934b04c694592a6276988630", 40 | "0xcdbfd34f687ced8c6968854f8a99ae47712c4f4183b78dcc4a903d1bfe8cbf60", 41 | "0x86f78c5416151fe3546dece84fda4b4b1e36089f2dbc48496faf3a950f16157c", 42 | "0x750839e9dbbd2a0910efe40f50b2f3b2f2f59f5580bb4b83bd8c1201cf9a010a" 43 | ] 44 | }, 45 | fuji: { 46 | url: 'https://api.avax-test.network/ext/bc/C/rpc', 47 | gasPrice: 225000000000, 48 | chainId: 43113, 49 | accounts: [process.env.PK || testPK] 50 | }, 51 | staging: { 52 | url: 'https://api.avax-test.network/ext/bc/C/rpc', 53 | gasPrice: 225000000000, 54 | chainId: 43113, 55 | accounts: [process.env.PK || testPK] 56 | }, 57 | mainnet: { 58 | url: 'https://api.avax.network/ext/bc/C/rpc', 59 | gasPrice: 60000000000, 60 | chainId: 43114, 61 | timeout: 900000000, 62 | accounts: [process.env.PK || testPK] 63 | }, 64 | local: { 65 | url: 'http://localhost:8545', 66 | }, 67 | }, 68 | gasReporter: { 69 | currency: 'USD', 70 | gasPrice: 100, 71 | enabled: true 72 | }, 73 | solidity: { 74 | compilers: [ {version: '0.6.12'} ], 75 | overrides: { 76 | "contracts/sales/AvalaunchSaleV2.sol": { 77 | version: '0.6.12', 78 | settings: { 79 | optimizer: { 80 | enabled: true, 81 | runs: 999999 82 | }, 83 | }, 84 | }, 85 | "contracts/sales/AvalaunchSale.sol": { 86 | version: '0.6.12', 87 | settings: { 88 | optimizer: { 89 | enabled: true, 90 | runs: 200 91 | }, 92 | }, 93 | }, 94 | "contracts/sales/SalesFactory.sol": { 95 | version: '0.6.12', 96 | settings: { 97 | optimizer: { 98 | enabled: true, 99 | runs: 999999 100 | }, 101 | }, 102 | }, 103 | "contracts/AvalaunchMarketplace.sol": { 104 | version: '0.6.12', 105 | settings: { 106 | optimizer: { 107 | enabled: true, 108 | runs: 999999 109 | }, 110 | }, 111 | }, 112 | "contracts/AllocationStaking.sol": { 113 | version: '0.6.12', 114 | settings: { 115 | optimizer: { 116 | enabled: true, 117 | runs: 200 118 | }, 119 | }, 120 | }, 121 | "contracts/AvalaunchCollateral.sol": { 122 | version: '0.6.12', 123 | settings: { 124 | optimizer: { 125 | enabled: true, 126 | runs: 999999 127 | }, 128 | }, 129 | }, 130 | }, 131 | settings: { 132 | optimizer: { 133 | enabled: true, 134 | runs: 200 135 | }, 136 | }, 137 | }, 138 | contractSizer: { 139 | alphaSort: true, 140 | runOnCompile: true, 141 | disambiguatePaths: false, 142 | } 143 | }; 144 | 145 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avalaunch-app/xava-protocol/e5c7d4a1d779ffd9d00d72bd264fb19dbdf2456e/logo.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "avalaunch-contracts", 3 | "version": "1.0.0", 4 | "description": "", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "keywords": [], 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "@types/chai-as-promised": "7.1.4", 13 | "@uniswap/lib": "4.0.1-alpha", 14 | "@uniswap/v2-core": "1.0.1", 15 | "@uniswap/v2-periphery": "1.1.0-beta.0", 16 | "bn.js": "5.2.0", 17 | "dotenv": "8.6.0", 18 | "git-module": "0.0.8", 19 | "hardhat-contract-sizer": "2.5.0", 20 | "hardhat-gas-reporter": "1.0.8", 21 | "hardhat-web3": "1.0.1", 22 | "scrypt": "github:barrysteyn/node-scrypt#fb60a8d3c158fe115a624b5ffa7480f3a24b03fb" 23 | }, 24 | "devDependencies": { 25 | "@chainlink/contracts": "0.0.10", 26 | "@nomiclabs/hardhat-ethers": "2.0.2", 27 | "@nomiclabs/hardhat-waffle": "2.0.1", 28 | "@nomiclabs/hardhat-web3": "2.0.0", 29 | "@openzeppelin/contracts": "3.4.1", 30 | "@openzeppelin/contracts-upgradeable": "3.4.1", 31 | "@openzeppelin/hardhat-upgrades": "1.6.0", 32 | "@tenderly/hardhat-tenderly": "1.0.12", 33 | "app-root-path": "3.0.0", 34 | "axios": "0.21.1", 35 | "bn-chai": "1.0.1", 36 | "chai": "4.3.4", 37 | "chai-as-promised": "7.1.1", 38 | "chai-bignumber": "3.0.0", 39 | "chai-bn": "0.2.2", 40 | "ethereum-waffle": "3.4.0", 41 | "ethers": "5.4.1", 42 | "form-data": "4.0.0", 43 | "git-branch": "2.0.1", 44 | "hardhat": "2.5.0", 45 | "isomorphic-fetch": "3.0.0", 46 | "solidity-coverage": "0.7.20", 47 | "stochasm": "0.5.0", 48 | "web3": "1.4.0", 49 | "zos-lib": "2.4.3" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /scripts/airdrops/deploy_AVAXAirdrop-ISA.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { saveContractAddress, getSavedContractAddresses } = require("../utils"); 3 | 4 | 5 | async function main() { 6 | const contracts = getSavedContractAddresses()[hre.network.name]; 7 | 8 | const AirdropAVAX = await hre.ethers.getContractFactory("AirdropAVAX"); 9 | const airdropContract = await AirdropAVAX.deploy(contracts['Admin']); 10 | await airdropContract.deployed(); 11 | 12 | console.log("AirdropAVAX contract is deployed to: ", airdropContract.address); 13 | saveContractAddress(hre.network.name, "AirdropAVAXIslander", airdropContract.address); 14 | } 15 | 16 | 17 | main() 18 | .then(() => process.exit(0)) 19 | .catch(error => { 20 | console.error(error); 21 | process.exit(1); 22 | }); 23 | -------------------------------------------------------------------------------- /scripts/airdrops/deploy_AVAXAirdrop-WOOD.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { saveContractAddress, getSavedContractAddresses } = require("../utils"); 3 | 4 | 5 | async function main() { 6 | const contracts = getSavedContractAddresses()[hre.network.name]; 7 | 8 | const AirdropAVAX = await hre.ethers.getContractFactory("AirdropAVAX"); 9 | const airdropContract = await AirdropAVAX.deploy(contracts['Admin']); 10 | await airdropContract.deployed(); 11 | 12 | console.log("AirdropAVAX contract is deployed to: ", airdropContract.address); 13 | saveContractAddress(hre.network.name, "AirdropAVAX-WOOD", airdropContract.address); 14 | } 15 | 16 | 17 | main() 18 | .then(() => process.exit(0)) 19 | .catch(error => { 20 | console.error(error); 21 | process.exit(1); 22 | }); 23 | -------------------------------------------------------------------------------- /scripts/airdrops/deploy_airdrop.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { saveContractAddress, getSavedContractAddresses } = require("../utils"); 3 | 4 | async function main() { 5 | const contracts = getSavedContractAddresses()[hre.network.name]; 6 | 7 | const Airdrop = await hre.ethers.getContractFactory("Airdrop"); 8 | const tokenAddress = '0x5FbDB2315678afecb367f032d93F642f64180aa3'; 9 | 10 | const airdropContract = await Airdrop.deploy(tokenAddress, contracts['Admin']); 11 | await airdropContract.deployed(); 12 | 13 | const tokenInstance = await hre.ethers.getContractAt('IERC20Metadata', tokenAddress); 14 | const symbol = await tokenInstance.symbol(); 15 | 16 | console.log("Airdrop contract is deployed to: ", airdropContract.address); 17 | saveContractAddress(hre.network.name, `Airdrop${symbol}`, airdropContract.address); 18 | } 19 | 20 | 21 | main() 22 | .then(() => process.exit(0)) 23 | .catch(error => { 24 | console.error(error); 25 | process.exit(1); 26 | }); 27 | -------------------------------------------------------------------------------- /scripts/airdrops/deploy_airdropALOT.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { saveContractAddress, getSavedContractAddresses } = require("../utils"); 3 | 4 | 5 | async function main() { 6 | const contracts = getSavedContractAddresses()[hre.network.name]; 7 | 8 | const Airdrop = await hre.ethers.getContractFactory("Airdrop"); 9 | const token = '0x093783055F9047C2BfF99c4e414501F8A147bC69'; 10 | const airdropContract = await Airdrop.deploy(token, contracts['Admin']); 11 | await airdropContract.deployed(); 12 | 13 | 14 | console.log("Airdrop contract is deployed to: ", airdropContract.address); 15 | saveContractAddress(hre.network.name, "AirdropALOT", airdropContract.address); 16 | } 17 | 18 | 19 | main() 20 | .then(() => process.exit(0)) 21 | .catch(error => { 22 | console.error(error); 23 | process.exit(1); 24 | }); 25 | -------------------------------------------------------------------------------- /scripts/airdrops/deploy_airdropAVAX.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { saveContractAddress, getSavedContractAddresses } = require("../utils"); 3 | 4 | async function main() { 5 | const contracts = getSavedContractAddresses()[hre.network.name]; 6 | 7 | const AirdropAVAX = await hre.ethers.getContractFactory("AirdropAVAX"); 8 | const airdropContract = await AirdropAVAX.deploy(contracts['Admin']); 9 | await airdropContract.deployed(); 10 | 11 | const tokenAddress = '0x5FbDB2315678afecb367f032d93F642f64180aa3'; 12 | 13 | const tokenInstance = await hre.ethers.getContractAt('IERC20Metadata', tokenAddress); 14 | const symbol = await tokenInstance.symbol(); 15 | 16 | console.log("AirdropAVAX contract is deployed to: ", airdropContract.address); 17 | saveContractAddress(hre.network.name, `AirdropAVAX-${symbol}`, airdropContract.address); 18 | } 19 | 20 | 21 | main() 22 | .then(() => process.exit(0)) 23 | .catch(error => { 24 | console.error(error); 25 | process.exit(1); 26 | }); 27 | -------------------------------------------------------------------------------- /scripts/airdrops/deploy_airdropCLY.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { saveContractAddress, getSavedContractAddresses } = require("../utils"); 3 | 4 | async function main() { 5 | const contracts = getSavedContractAddresses()[hre.network.name]; 6 | 7 | const Airdrop = await hre.ethers.getContractFactory("Airdrop"); 8 | const tokenAddress = '0xec3492a2508DDf4FDc0cD76F31f340b30d1793e6'; 9 | 10 | const airdropContract = await Airdrop.deploy(tokenAddress, contracts['Admin']); 11 | await airdropContract.deployed(); 12 | 13 | const tokenInstance = await hre.ethers.getContractAt('IERC20Metadata', tokenAddress); 14 | const symbol = await tokenInstance.symbol(); 15 | 16 | console.log("Airdrop contract is deployed to: ", airdropContract.address); 17 | saveContractAddress(hre.network.name, `Airdrop${symbol}`, airdropContract.address); 18 | } 19 | 20 | 21 | main() 22 | .then(() => process.exit(0)) 23 | .catch(error => { 24 | console.error(error); 25 | process.exit(1); 26 | }); 27 | -------------------------------------------------------------------------------- /scripts/airdrops/deploy_airdropDEG.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { saveContractAddress, getSavedContractAddresses } = require("../utils"); 3 | 4 | 5 | async function main() { 6 | const contracts = getSavedContractAddresses()[hre.network.name]; 7 | 8 | const Airdrop = await hre.ethers.getContractFactory("Airdrop"); 9 | const token = '0x9f285507Ea5B4F33822CA7aBb5EC8953ce37A645'; 10 | const airdropContract = await Airdrop.deploy(token, contracts['Admin']); 11 | await airdropContract.deployed(); 12 | 13 | 14 | console.log("Airdrop contract is deployed to: ", airdropContract.address); 15 | saveContractAddress(hre.network.name, "AirdropDEG", airdropContract.address); 16 | } 17 | 18 | 19 | main() 20 | .then(() => process.exit(0)) 21 | .catch(error => { 22 | console.error(error); 23 | process.exit(1); 24 | }); 25 | -------------------------------------------------------------------------------- /scripts/airdrops/deploy_airdropDFIAT.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { saveContractAddress, getSavedContractAddresses } = require("../utils"); 3 | 4 | 5 | async function main() { 6 | const contracts = getSavedContractAddresses()[hre.network.name]; 7 | 8 | const Airdrop = await hre.ethers.getContractFactory("Airdrop"); 9 | const token = '0xAfE3d2A31231230875DEe1fa1eEF14a412443d22'; 10 | const airdropContract = await Airdrop.deploy(token, contracts['Admin']); 11 | await airdropContract.deployed(); 12 | 13 | 14 | console.log("Airdrop contract is deployed to: ", airdropContract.address); 15 | saveContractAddress(hre.network.name, "AirdropDFIAT", airdropContract.address); 16 | } 17 | 18 | 19 | main() 20 | .then(() => process.exit(0)) 21 | .catch(error => { 22 | console.error(error); 23 | process.exit(1); 24 | }); 25 | -------------------------------------------------------------------------------- /scripts/airdrops/deploy_airdropHEC.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { saveContractAddress, getSavedContractAddresses } = require("../utils"); 3 | 4 | 5 | async function main() { 6 | const contracts = getSavedContractAddresses()[hre.network.name]; 7 | 8 | const Airdrop = await hre.ethers.getContractFactory("Airdrop"); 9 | const token = '0xC7f4debC8072e23fe9259A5C0398326d8EfB7f5c'; 10 | const airdropContract = await Airdrop.deploy(token, contracts['Admin']); 11 | await airdropContract.deployed(); 12 | 13 | 14 | console.log("Airdrop contract is deployed to: ", airdropContract.address); 15 | saveContractAddress(hre.network.name, "AirdropHEC", airdropContract.address); 16 | } 17 | 18 | 19 | main() 20 | .then(() => process.exit(0)) 21 | .catch(error => { 22 | console.error(error); 23 | process.exit(1); 24 | }); 25 | -------------------------------------------------------------------------------- /scripts/airdrops/deploy_airdropHON.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { saveContractAddress, getSavedContractAddresses } = require("../utils"); 3 | 4 | 5 | async function main() { 6 | const contracts = getSavedContractAddresses()[hre.network.name]; 7 | 8 | const Airdrop = await hre.ethers.getContractFactory("Airdrop"); 9 | const token = '0xed2b42d3c9c6e97e11755bb37df29b6375ede3eb'; 10 | const airdropContract = await Airdrop.deploy(token, contracts['Admin']); 11 | await airdropContract.deployed(); 12 | 13 | 14 | console.log("Airdrop contract is deployed to: ", airdropContract.address); 15 | saveContractAddress(hre.network.name, "AirdropHON", airdropContract.address); 16 | } 17 | 18 | 19 | main() 20 | .then(() => process.exit(0)) 21 | .catch(error => { 22 | console.error(error); 23 | process.exit(1); 24 | }); 25 | -------------------------------------------------------------------------------- /scripts/airdrops/deploy_airdropISA.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { saveContractAddress, getSavedContractAddresses } = require("../utils"); 3 | 4 | 5 | async function main() { 6 | const contracts = getSavedContractAddresses()[hre.network.name]; 7 | 8 | const Airdrop = await hre.ethers.getContractFactory("Airdrop"); 9 | const token = '0x3eefb18003d033661f84e48360ebecd181a84709'; 10 | 11 | let airdropContract; 12 | 13 | for (let i = 0; i < 5; i++) { 14 | airdropContract = await Airdrop.deploy(token, contracts['Admin']); 15 | await airdropContract.deployed(); 16 | console.log("Airdrop contract is deployed to: ", airdropContract.address); 17 | saveContractAddress(hre.network.name, `AirdropISA-Portion-${i+1}`, airdropContract.address); 18 | } 19 | 20 | } 21 | 22 | 23 | main() 24 | .then(() => process.exit(0)) 25 | .catch(error => { 26 | console.error(error); 27 | process.exit(1); 28 | }); 29 | -------------------------------------------------------------------------------- /scripts/airdrops/deploy_airdropSale.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { saveContractAddress, getSavedContractAddresses } = require("../utils"); 3 | 4 | async function main() { 5 | const contracts = getSavedContractAddresses()[hre.network.name]; 6 | 7 | // Add array of ERC20 tokens to distribute (allowed to be empty) 8 | const tokenAddresses = []; 9 | // Mark if AVAX airdrop is included 10 | const includesAVAX = true; 11 | // Set sale suffix - main token symbol 12 | const saleSuffix = ''; 13 | 14 | const Airdrop = await hre.ethers.getContractFactory("AirdropSale"); 15 | const airdropContract = await Airdrop.deploy(tokenAddresses, contracts['Admin'], includesAVAX); 16 | await airdropContract.deployed(); 17 | 18 | console.log("Airdrop contract is deployed to: ", airdropContract.address); 19 | saveContractAddress(hre.network.name, `Airdrop${saleSuffix}`, airdropContract.address); 20 | } 21 | 22 | 23 | main() 24 | .then(() => process.exit(0)) 25 | .catch(error => { 26 | console.error(error); 27 | process.exit(1); 28 | }); 29 | -------------------------------------------------------------------------------- /scripts/airdrops/deploy_vested_airdrop.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { saveContractAddress, getSavedContractAddresses } = require("../utils"); 3 | 4 | const delay = ms => new Promise(res => setTimeout(res, ms)); 5 | const delayLength = 3000; 6 | 7 | async function main() { 8 | const contracts = getSavedContractAddresses()[hre.network.name]; 9 | 10 | const Airdrop = await hre.ethers.getContractFactory("Airdrop"); 11 | // Token which is being airdropped 12 | const tokenAddress = '0xd1c3f94DE7e5B45fa4eDBBA472491a9f4B166FC4'; 13 | 14 | const numberOfPortions = 26; 15 | 16 | let airdropContract; 17 | 18 | let deployedAirdropContracts = []; 19 | 20 | const tokenInstance = await hre.ethers.getContractAt('IERC20Metadata', tokenAddress); 21 | const symbol = await tokenInstance.symbol(); 22 | 23 | for(let i = 0; i < numberOfPortions; i++) { 24 | airdropContract = await Airdrop.deploy(tokenAddress, contracts['Admin']); 25 | await airdropContract.deployed(); 26 | deployedAirdropContracts.push(airdropContract.address); 27 | console.log(airdropContract.address); 28 | await delay(delayLength); 29 | saveContractAddress(hre.network.name, `Airdrop${symbol}-Portion-${i+1}`, airdropContract.address); 30 | } 31 | 32 | console.log("Vested Airdrop contracts are deployed to the following addresses: ", deployedAirdropContracts); 33 | } 34 | 35 | 36 | main() 37 | .then(() => process.exit(0)) 38 | .catch(error => { 39 | console.error(error); 40 | process.exit(1); 41 | }); 42 | -------------------------------------------------------------------------------- /scripts/configs/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "fuji" : { 3 | "token": { 4 | "tokenName": "STAGING-FUJI-TEST", 5 | "symbol": "SDT-1", 6 | "totalSupply": "100000000000000000000000000", 7 | "decimals": 18 8 | }, 9 | "admins" : [ 10 | "0x0c3e4509ee2EdD1BE61230BdE49b2FfC7a8ca88b", 11 | "0x85E3e0224a199f9e908AB4E3525Dd5504569EE5a", 12 | "0x2655D93eF7FfBF780aB9259825A8bF2b3d8A703A", 13 | "0x094028E04c1FADf12F5a4Fe6C1b9D2062a252a17", 14 | "0xD0CaE2309f322E24fBBc7E9D5F4995B02eF901e4", 15 | "0xa91a2a8e47fa3fbaEed92Cc3D00C61712b9781A5", 16 | "0x3Fa80eAe09D3006A230e3eB8244C2035bABF8273" 17 | ], 18 | "moderator": "0x0c3e4509ee2EdD1BE61230BdE49b2FfC7a8ca88b", 19 | "allocationStakingRPS": "0.01", 20 | "delayBeforeStart": 200, 21 | "depositFeePercent": "2", 22 | "depositFeePrecision": "100", 23 | "initialRewardsAllocationStaking": "5000000", 24 | "xavaPoolAllocPoints": "100", 25 | "placeholderPoolAllocPoints": "50", 26 | "postSaleWithdrawPenaltyLength": 432000, 27 | "postSaleWithdrawPenaltyPercent": 10000, 28 | "postSaleWithdrawPenaltyPrecision": 100000 29 | }, 30 | "mainnet" : { 31 | "token": { 32 | "tokenName": "XavaToken", 33 | "symbol": "XAVA", 34 | "totalSupply": "100000000000000000000000000", 35 | "decimals": 18 36 | }, 37 | "admins" : [ 38 | "0x48e9542EF042aD6E65aBE996C94c599CceD8BA4c", 39 | "0x72fB4Ae02f97633B26314372f20957aeB4434643", 40 | "0xC6737103b9aAFe3707B7bA3be0Fe740bb2433010", 41 | "0x9c9d627193B87d14614066ecD08b1ACEAe43d9cf", 42 | "0xD0CaE2309f322E24fBBc7E9D5F4995B02eF901e4" 43 | ], 44 | "moderator": "0xD0CaE2309f322E24fBBc7E9D5F4995B02eF901e4", 45 | "allocationStakingRPS": "0.01", 46 | "delayBeforeStart": 1000, 47 | "depositFeePercent": "2", 48 | "depositFeePrecision": "100", 49 | "initialRewardsAllocationStaking": "320000", 50 | "xavaPoolAllocPoints": "50", 51 | "placeholderPoolAllocPoints": "50", 52 | "postSaleWithdrawPenaltyLength": 432000, 53 | "postSaleWithdrawPenaltyPercent": 100000, 54 | "postSaleWithdrawPenaltyPrecision": 1000000 55 | }, 56 | "local" : { 57 | "token": { 58 | "tokenName": "XAVA-MOCK-V3", 59 | "symbol": "MCK-V3", 60 | "totalSupply": "100000000000000000000000000", 61 | "decimals": 18 62 | }, 63 | "admins" : [ 64 | "0x0c3e4509ee2EdD1BE61230BdE49b2FfC7a8ca88b", 65 | "0x85E3e0224a199f9e908AB4E3525Dd5504569EE5a", 66 | "0x2655D93eF7FfBF780aB9259825A8bF2b3d8A703A", 67 | "0x094028E04c1FADf12F5a4Fe6C1b9D2062a252a17", 68 | "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266" 69 | ], 70 | "allocationStakingRPS": "0.01", 71 | "delayBeforeStart": 500, 72 | "depositFeePercent": "2", 73 | "depositFeePrecision": "100", 74 | "initialRewardsAllocationStaking": "5000000", 75 | "placeholderPoolAllocPoints": "50", 76 | "xavaPoolAllocPoints": "100", 77 | "postSaleWithdrawPenaltyLength": 432000, 78 | "postSaleWithdrawPenaltyPercent": 10, 79 | "placeholderPoolAllocPoints": "50", 80 | "postSaleWithdrawPenaltyPrecision": 1000000 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /scripts/configs/saleConfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "mainnet": { 3 | "saleName": "Arrow Markets", 4 | "saleEndTime": "1715509800", 5 | "tokenAddress": "0x5c5e384Bd4e36724B2562cCAA582aFd125277C9B", 6 | "totalTokens": "720000", 7 | "tokenPriceInAvax": "0.0107459", 8 | "portionVestingPrecision": 1000000, 9 | "registrationDepositAVAX": "1", 10 | "unlockingTimes": [ 11 | 1715745600, 12 | 1716350400, 13 | 1716955200, 14 | 1717560000, 15 | 1718164800, 16 | 1718769600, 17 | 1719374400, 18 | 1719979200, 19 | 1720584000, 20 | 1721188800, 21 | 1721793600, 22 | 1722398400, 23 | 1723003200, 24 | 1723608000, 25 | 1724212800, 26 | 1724817600, 27 | 1725422400 28 | ], 29 | "portionPercents": [ 30 | 250000, 31 | 46875, 32 | 46875, 33 | 46875, 34 | 46875, 35 | 46875, 36 | 46875, 37 | 46875, 38 | 46875, 39 | 46875, 40 | 46875, 41 | 46875, 42 | 46875, 43 | 46875, 44 | 46875, 45 | 46875, 46 | 46875 47 | ] 48 | }, 49 | "mainnet-gold": { 50 | "tokenAddress": "0xFd538CA3f58dC309dA55B11f007ff53fb4602876", 51 | "totalTokens": "4500000", 52 | "tokenPriceInUSD": "0.0333", 53 | "tokenPriceInAvax": "0.00186659192", 54 | "saleOwner": "0x4F92C01bBfe5918f0FC0bdfE4Af6f7edD1eD85A5", 55 | "registrationStartAt": 1664118000, 56 | "registrationLength": 702000, 57 | "delayBetweenRegistrationAndSale": 43199, 58 | "validatorRoundLength": 1, 59 | "stakingRoundLength": 86400, 60 | "boosterRoundLength": 16200, 61 | "TGE": "1665243000", 62 | "portionVestingPrecision": 100000, 63 | "stakingRoundId": 2, 64 | "registrationDepositAVAX": "1", 65 | "maxVestingTimeShift": 2592000, 66 | "updateTokenPriceInAVAXPercentageThreshold": 30, 67 | "updateTokenPriceInAVAXTimeLimit": 600, 68 | "unlockingTimes": [ 69 | 10000, 70 | 1730, 71 | 1730, 72 | 1730, 73 | 1730, 74 | 1730, 75 | 1730, 76 | 1730, 77 | 1730, 78 | 1730, 79 | 1730, 80 | 1730, 81 | 1730, 82 | 1730, 83 | 1730, 84 | 1730, 85 | 1730, 86 | 1730, 87 | 1730, 88 | 1730, 89 | 1730, 90 | 1730, 91 | 1730, 92 | 1730, 93 | 1730, 94 | 1730, 95 | 1730, 96 | 1730, 97 | 1730, 98 | 1730, 99 | 1730, 100 | 1730, 101 | 1730, 102 | 1730, 103 | 1730, 104 | 1730, 105 | 1730, 106 | 1730, 107 | 1730, 108 | 1730, 109 | 1730, 110 | 1730, 111 | 1730, 112 | 1730, 113 | 1730, 114 | 1730, 115 | 1730, 116 | 1730, 117 | 1730, 118 | 1730, 119 | 1730, 120 | 1730, 121 | 1770 122 | ], 123 | "portionPercents": [ 124 | 1665243000, 125 | 1681572600, 126 | 1682177400, 127 | 1682782200, 128 | 1683387000, 129 | 1683991800, 130 | 1684596600, 131 | 1685201400, 132 | 1685806200, 133 | 1686411000, 134 | 1687015800, 135 | 1687620600, 136 | 1688225400, 137 | 1688830200, 138 | 1689435000, 139 | 1690039800, 140 | 1690644600, 141 | 1691249400, 142 | 1691854200, 143 | 1692459000, 144 | 1693063800, 145 | 1693668600, 146 | 1694273400, 147 | 1694878200, 148 | 1695483000, 149 | 1696087800, 150 | 1696692600, 151 | 1697297400, 152 | 1697902200, 153 | 1698507000, 154 | 1699111800, 155 | 1699716600, 156 | 1700321400, 157 | 1700926200, 158 | 1701531000, 159 | 1702135800, 160 | 1702740600, 161 | 1703345400, 162 | 1703950200, 163 | 1704555000, 164 | 1705159800, 165 | 1705764600, 166 | 1706369400, 167 | 1706974200, 168 | 1707579000, 169 | 1708183800, 170 | 1708788600, 171 | 1709393400, 172 | 1709998200, 173 | 1710603000, 174 | 1711207800, 175 | 1711812600, 176 | 1712417400 177 | ] 178 | }, 179 | "staging": { 180 | "tokenAddress": "0xD95d874e6bc638A25ec7FbA5224b21f5e18B308f", 181 | "dexalotPortfolio": "0xD95d874e6bc638A25ec7FbA5224b21f5e18B308f", 182 | "dexalotUnlockingTime": "2037949300", 183 | "totalTokens": "3214285", 184 | "tokenPriceUSD": "0.28", 185 | "tokenPriceInAvax": "0.00276926", 186 | "saleOwner": "0xa91a2a8e47fa3fbaEed92Cc3D00C61712b9781A5", 187 | "registrationStartAt": 2037611393, 188 | "registrationLength": 313200, 189 | "delayBetweenRegistrationAndSale": 86400, 190 | "validatorRoundLength": 43200, 191 | "stakingRoundLength": 43200, 192 | "TGE": 2037949300, 193 | "portionVestingPrecision": 10000, 194 | "stakingRoundId": 2, 195 | "registrationDepositAVAX": "1", 196 | "maxVestingTimeShift": 2592000, 197 | "updateTokenPriceInAVAXPercentageThreshold": 30, 198 | "updateTokenPriceInAVAXTimeLimit": 600, 199 | "unlockingTimes": [ 200 | 1637612173, 201 | 1637612233, 202 | 1637612293, 203 | 1637612353, 204 | 1637612413, 205 | 1637612473, 206 | 1637612533, 207 | 1637612593, 208 | 1637612653, 209 | 1637612713, 210 | 1637612773, 211 | 1637612833, 212 | 1637612893, 213 | 1637612953 214 | ], 215 | "portionPercents": [3500,500,500,500,500,500,500,500,500,500,500,500,500,500] 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /scripts/deployment/deploy_collateral_with_proxy.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { getSavedContractAddresses, saveContractAddress} = require('../utils'); 3 | const ethers = require("ethers"); 4 | const c = require('../configs/config.json'); 5 | const config = c[hre.network.name]; 6 | 7 | async function main() { 8 | await hre.run('compile'); 9 | const contracts = getSavedContractAddresses()[hre.network.name]; 10 | const proxyAdmin = contracts["ProxyAdmin"]; 11 | 12 | console.log(`ProxyAdmin address: ${proxyAdmin}`); 13 | 14 | const collateralFactory = await hre.ethers.getContractFactory("AvalaunchCollateral"); 15 | const collateral = await collateralFactory.deploy(); 16 | await collateral.deployed(); 17 | 18 | console.log(`Collateral implementation address: ${collateral.address}`); 19 | saveContractAddress(hre.network.name, "AvalaunchCollateral", collateral.address); 20 | 21 | const methodId = (ethers.utils.keccak256(ethers.utils.toUtf8Bytes("initialize(address,address,uint256)"))).substring(0,10); // '0x' + 4 bytes 22 | const types = ['address','address','uint256']; // Types to encode 23 | const values = [config['moderator'], contracts['Admin'], hre.network.name === 'mainnet' ? 43114 : 43113]; // Values to encode 24 | 25 | const abi = new ethers.utils.AbiCoder(); // Get abi coder instance 26 | let data = methodId + abi.encode(types, values).substring(2); // Generate calldata 27 | console.log(`Calldata: ${data}`); 28 | 29 | const proxyFactory = await hre.ethers.getContractFactory("contracts/openzeppelin/TransparentUpgradeableProxy.sol:TransparentUpgradeableProxy"); 30 | const proxy = await proxyFactory.deploy(collateral.address, proxyAdmin, data); 31 | await proxy.deployed(); 32 | 33 | console.log(`Collateral proxy address: ${proxy.address}`); 34 | saveContractAddress(hre.network.name, "AvalaunchCollateralProxy", proxy.address); 35 | 36 | console.log("Done!"); 37 | } 38 | 39 | // We recommend this pattern to be able to use async/await everywhere 40 | // and properly handle errors. 41 | main() 42 | .then(() => process.exit(0)) 43 | .catch(error => { 44 | console.error(error); 45 | process.exit(1); 46 | }); 47 | -------------------------------------------------------------------------------- /scripts/deployment/deploy_devtoken.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { saveContractAddress } = require('../utils') 3 | 4 | async function main() { 5 | const tokenName = "XavaDevTokenAlloStaking"; 6 | const symbol = "XavaDTAllo"; 7 | const totalSupply = ethers.utils.parseEther('10000'); 8 | const decimals = 18; 9 | 10 | const DevToken = await hre.ethers.getContractFactory("DevToken"); 11 | const token = await DevToken.deploy(tokenName, symbol, totalSupply, decimals); 12 | await token.deployed(); 13 | console.log("DevTokenAlloStaking deployed to: ", token.address); 14 | 15 | saveContractAddress(hre.network.name, "DevTokenAlloStaking", token.address); 16 | } 17 | 18 | 19 | main() 20 | .then(() => process.exit(0)) 21 | .catch(error => { 22 | console.error(error); 23 | process.exit(1); 24 | }); 25 | -------------------------------------------------------------------------------- /scripts/deployment/deploy_farm.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { getSavedContractAddresses, saveContractAddress } = require('../utils') 3 | const { ethers, web3 } = hre 4 | const BigNumber = ethers.BigNumber 5 | 6 | async function main() { 7 | 8 | const contracts = getSavedContractAddresses()[hre.network.name]; 9 | 10 | const startSecond = 1627309218; 11 | 12 | const rewardsPerSecond = ethers.utils.parseEther("0.1"); 13 | 14 | const allocPoints = { 15 | lp: 400, 16 | placeHolder: 800 17 | }; 18 | 19 | const FarmingXava = await hre.ethers.getContractFactory('FarmingXava'); 20 | 21 | const farmingXava = await FarmingXava.deploy( 22 | contracts["XavaToken"], 23 | rewardsPerSecond, 24 | startSecond 25 | ); 26 | await farmingXava.deployed(); 27 | console.log('FarmingXava deployed: ', farmingXava.address); 28 | saveContractAddress(hre.network.name, 'FarmingXava', farmingXava.address); 29 | 30 | await farmingXava.add(allocPoints.lp, contracts['LpToken'], true); 31 | await farmingXava.add(allocPoints.placeHolder, contracts['DevToken'], true); 32 | 33 | const xava = await hre.ethers.getContractAt('XavaToken', contracts['XavaToken']); 34 | const devToken = await hre.ethers.getContractAt('DevToken', contracts['DevToken']); 35 | 36 | let totalRewards = ethers.utils.parseEther("5000"); 37 | await xava.approve(farmingXava.address, totalRewards); 38 | console.log('Approval for farm done properly.'); 39 | 40 | const totalSupplyDevToken = ethers.utils.parseEther('10000'); 41 | await devToken.approve(farmingXava.address, totalSupplyDevToken); 42 | console.log('Dev token successfully approved.'); 43 | 44 | await farmingXava.deposit(1, totalSupplyDevToken); 45 | console.log('Dev token deposited amount: ', totalSupplyDevToken); 46 | 47 | await farmingXava.fund(totalRewards); 48 | console.log('Funded farm.'); 49 | 50 | } 51 | 52 | // We recommend this pattern to be able to use async/await everywhere 53 | // and properly handle errors. 54 | main() 55 | .then(() => process.exit(0)) 56 | .catch(error => { 57 | console.error(error); 58 | process.exit(1); 59 | }); 60 | -------------------------------------------------------------------------------- /scripts/deployment/deploy_marketplace_with_proxy.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { getSavedContractAddresses, saveContractAddress} = require('../utils'); 3 | const ethers = require("ethers"); 4 | const c = require('../configs/config.json'); 5 | const config = c[hre.network.name]; 6 | 7 | async function main() { 8 | await hre.run('compile'); 9 | const contracts = getSavedContractAddresses()[hre.network.name]; 10 | const proxyAdmin = contracts["ProxyAdmin"]; 11 | 12 | const feePercentage = 200; 13 | const feePrecision = 10000; 14 | 15 | console.log(`ProxyAdmin address: ${proxyAdmin}`); 16 | 17 | const marketplaceFactory = await hre.ethers.getContractFactory("AvalaunchMarketplace"); 18 | const marketplace = await marketplaceFactory.deploy(); 19 | await marketplace.deployed(); 20 | 21 | console.log(`Marketplace implementation address: ${marketplace.address}`); 22 | saveContractAddress(hre.network.name, "AvalaunchMarketplace", marketplace.address); 23 | 24 | const methodId = (ethers.utils.keccak256(ethers.utils.toUtf8Bytes("initialize(address,address,uint256,uint256)"))).substring(0,10); // '0x' + 4 bytes 25 | const types = ['address','address','uint256','uint256']; // Types to encode 26 | const values = [contracts['Admin'], contracts['SalesFactory'], feePercentage, feePrecision]; // Values to encode 27 | 28 | const abi = new ethers.utils.AbiCoder(); // Get abi coder instance 29 | let data = methodId + abi.encode(types, values).substring(2); // Generate calldata 30 | console.log(`Calldata: ${data}`); 31 | 32 | const proxyFactory = await hre.ethers.getContractFactory("contracts/openzeppelin/TransparentUpgradeableProxy.sol:TransparentUpgradeableProxy"); 33 | const proxy = await proxyFactory.deploy(marketplace.address, proxyAdmin, data); 34 | await proxy.deployed(); 35 | 36 | console.log(`Marketplace proxy address: ${proxy.address}`); 37 | saveContractAddress(hre.network.name, "AvalaunchMarketplaceProxy", proxy.address); 38 | 39 | console.log("Done!"); 40 | } 41 | 42 | // We recommend this pattern to be able to use async/await everywhere 43 | // and properly handle errors. 44 | main() 45 | .then(() => process.exit(0)) 46 | .catch(error => { 47 | console.error(error); 48 | process.exit(1); 49 | }); 50 | -------------------------------------------------------------------------------- /scripts/deployment/deploy_mock_token.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { saveContractAddress } = require('../utils') 3 | 4 | async function main() { 5 | const tokenName = "COB - Mock ERC20"; 6 | const symbol = "COB"; 7 | const totalSupply = "2000000000000000000000000"; 8 | const decimals = 18; 9 | 10 | const MCK1 = await hre.ethers.getContractFactory("XavaToken"); 11 | const token = await MCK1.deploy(tokenName, symbol, totalSupply, decimals); 12 | await token.deployed(); 13 | console.log("COB deployed to: ", token.address); 14 | 15 | saveContractAddress(hre.network.name, "COB-MOCK-TOKEN", token.address); 16 | } 17 | 18 | 19 | main() 20 | .then(() => process.exit(0)) 21 | .catch(error => { 22 | console.error(error); 23 | process.exit(1); 24 | }); 25 | -------------------------------------------------------------------------------- /scripts/deployment/deploy_sales.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { saveContractAddress, getSavedContractAddresses } = require('../utils') 3 | const { redOut, greenOut } = require('../styling'); 4 | const config = require("../configs/saleConfig.json"); 5 | const { ethers } = hre 6 | 7 | async function getCurrentBlockTimestamp() { 8 | return (await ethers.provider.getBlock('latest')).timestamp; 9 | } 10 | 11 | const delay = ms => new Promise(res => setTimeout(res, ms)); 12 | const delayLength = 3000; 13 | 14 | async function main() { 15 | 16 | const contracts = getSavedContractAddresses()[hre.network.name]; 17 | const c = config[hre.network.name]; 18 | 19 | const salesFactory = await hre.ethers.getContractAt('SalesFactory', contracts['SalesFactory']); 20 | 21 | await(await salesFactory.deploySale()).wait(); 22 | console.log('Sale is deployed successfully.'); 23 | 24 | await delay(delayLength); 25 | 26 | const lastDeployedSale = await salesFactory.getLastDeployedSale(); 27 | console.log('Deployed Sale address is: ', lastDeployedSale); 28 | saveContractAddress(hre.network.name, "LatestSale", lastDeployedSale); 29 | 30 | const sale = await hre.ethers.getContractAt('AvalaunchSale', lastDeployedSale); 31 | console.log(`Successfully instantiated sale contract at address: ${lastDeployedSale}.`); 32 | 33 | const totalTokens = ethers.utils.parseEther(c['totalTokens']); 34 | console.log('Total tokens to sell: ', c['totalTokens']); 35 | 36 | const tokenPriceInAvax = ethers.utils.parseEther(c['tokenPriceInAvax']); 37 | console.log('Token price in AVAX: ', c['tokenPriceInAvax']); 38 | 39 | const registrationDepositAVAX = ethers.utils.parseEther(c['registrationDepositAVAX']); 40 | console.log('Registration deposit AVAX is: ', c['registrationDepositAVAX']); 41 | 42 | const saleOwner = c['saleOwner']; 43 | console.log('Sale owner is: ', c['saleOwner']); 44 | 45 | const registrationStart = c['registrationStartAt']; 46 | const registrationEnd = registrationStart + c['registrationLength']; 47 | const validatorRound = registrationEnd + c['delayBetweenRegistrationAndSale']; 48 | const stakingRound = validatorRound + c['validatorRoundLength']; 49 | const boosterRound = stakingRound + c['stakingRoundLength']; 50 | const saleEndTime = boosterRound + c['boosterRoundLength']; 51 | 52 | const tokensUnlockTime = c['TGE']; 53 | 54 | const tokenPriceInUSD = hre.ethers.utils.parseEther(c['tokenPriceInUSD']); 55 | 56 | await(await sale.setSaleParams( 57 | c['tokenAddress'], 58 | saleOwner, 59 | tokenPriceInAvax.toString(), 60 | totalTokens.toString(), 61 | saleEndTime, 62 | c['portionVestingPrecision'], 63 | c['stakingRoundId'], 64 | registrationDepositAVAX.toString(), 65 | tokenPriceInUSD 66 | )).wait(); 67 | console.log('Sale Params set successfully.'); 68 | 69 | await delay(delayLength); 70 | 71 | console.log('Setting registration time.'); 72 | await sale.setRegistrationTime( 73 | registrationStart, 74 | registrationEnd 75 | ); 76 | console.log('Registration time set.'); 77 | 78 | await delay(delayLength); 79 | 80 | console.log('Setting rounds.'); 81 | await sale.setRounds( 82 | [validatorRound, stakingRound, boosterRound], 83 | [ 84 | ethers.utils.parseEther('7000000000'), 85 | ethers.utils.parseEther('7000000000'), 86 | ethers.utils.parseEther('7000000000') 87 | ] 88 | ); 89 | 90 | const unlockingTimes = c['unlockingTimes']; 91 | const percents = c['portionPercents']; 92 | 93 | console.log('Unlocking times: ', unlockingTimes); 94 | console.log('Percents: ', percents); 95 | console.log('Precision for vesting: ', c['portionVestingPrecision']); 96 | console.log('Max vesting time shift in seconds: ', c['maxVestingTimeShift']); 97 | 98 | await delay(delayLength); 99 | 100 | console.log('Setting vesting params.'); 101 | await sale.setVestingParams(unlockingTimes, percents, c['maxVestingTimeShift']); 102 | console.log('Vesting parameters set successfully.'); 103 | 104 | await sale.setUpdateTokenPriceInAVAXParams(c['updateTokenPriceInAVAXPercentageThreshold'], c['updateTokenPriceInAVAXTimeLimit']); 105 | console.log('Token price updating parameters set.'); 106 | 107 | // add dexalot portfolio support 108 | await sale.setAndSupportDexalotPortfolio(c['dexalotPortfolio'], c['dexalotUnlockingTime']) 109 | .then(() => console.log(greenOut('Dexalot supported.'))) 110 | .catch((err) => console.log(redOut('Dexalot not supported.'))); 111 | 112 | console.log({ 113 | saleAddress: lastDeployedSale, 114 | saleToken: c['tokenAddress'], 115 | saleOwner, 116 | tokenPriceInAvax: tokenPriceInAvax.toString(), 117 | totalTokens: totalTokens.toString(), 118 | saleEndTime, 119 | tokensUnlockTime, 120 | registrationStart, 121 | registrationEnd, 122 | validatorRound, 123 | stakingRound, 124 | registrationDepositAVAX: c['registrationDepositAVAX'], 125 | dexalotPortfolio: c['dexalotPortfolio'] || "Not present in config", 126 | dexalotUnlockingTime: c['dexalotUnlockingTime'] || "Not present in config" 127 | }); 128 | 129 | const collateral = await hre.ethers.getContractAt("AvalaunchCollateral", contracts['AvalaunchCollateralProxy']); 130 | await collateral.approveSale(sale.address); 131 | console.log('Sale approved on collateral.'); 132 | } 133 | 134 | 135 | main() 136 | .then(() => process.exit(0)) 137 | .catch(error => { 138 | console.error(error); 139 | process.exit(1); 140 | }); 141 | -------------------------------------------------------------------------------- /scripts/deployment/deploy_sales_factory.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { getSavedContractAddresses, saveContractAddress} = require('../utils'); 3 | const { ethers } = hre; 4 | const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; 5 | 6 | async function main() { 7 | const contracts = getSavedContractAddresses()[hre.network.name]; 8 | 9 | const SalesFactory = await ethers.getContractFactory("SalesFactory"); 10 | const salesFactory = await SalesFactory.deploy( 11 | contracts['Admin'], 12 | contracts['AllocationStakingProxy'], 13 | contracts['AvalaunchCollateralProxy'], 14 | ZERO_ADDRESS, 15 | '0x0c3e4509ee2EdD1BE61230BdE49b2FfC7a8ca88b' // Staging mod 16 | ); 17 | await salesFactory.deployed(); 18 | 19 | saveContractAddress(hre.network.name, "SalesFactory", salesFactory.address); 20 | console.log('Sales factory deployed to: ', salesFactory.address); 21 | } 22 | 23 | main() 24 | .then(() => process.exit(0)) 25 | .catch(error => { 26 | console.error(error); 27 | process.exit(1); 28 | }); 29 | -------------------------------------------------------------------------------- /scripts/deployment/deploy_sales_staging.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { getSavedContractAddresses, saveContractAddress } = require('../utils'); 3 | const { ethers } = hre; 4 | const { greenOut, boldOut } = require('../styling'); 5 | const config = require("../configs/saleConfig.json"); 6 | 7 | const getCurrentBlockTimestamp = async () => { 8 | return (await ethers.provider.getBlock('latest')).timestamp; 9 | } 10 | 11 | const delay = ms => new Promise(res => setTimeout(res, ms)); 12 | const delayLength = 3000; 13 | 14 | const main = async () => { 15 | 16 | const contracts = getSavedContractAddresses()[hre.network.name]; 17 | const c = config[hre.network.name]; 18 | 19 | // instantiate salesFactory 20 | const salesFactory = await hre.ethers.getContractAt('SalesFactory', contracts['SalesFactory']); 21 | 22 | // deploy new sale and await the block after 23 | await(await salesFactory.deploySale()).wait(); 24 | console.log(boldOut('Sale deployed successfully.')); 25 | await delay(delayLength); 26 | 27 | // retrieve the sale deployed and save the address 28 | const lastDeployedSale = await salesFactory.getLastDeployedSale(); 29 | saveContractAddress(hre.network.name,'LatestSale', lastDeployedSale); 30 | console.log(`Deployed sale address: ${greenOut(lastDeployedSale)}`); 31 | console.log('Sub-operations:'); 32 | // instantiate deployed sale contract 33 | const sale = await hre.ethers.getContractAt('AvalaunchSale', lastDeployedSale); 34 | console.log(' - Successfully instantiated sale contract.'); 35 | 36 | // retrieve sale deployer address 37 | const wallet = new hre.ethers.Wallet(process.env.PK); 38 | const saleOwner = wallet.address; 39 | console.log(` - saleOwner address: ${greenOut(saleOwner)}`); 40 | 41 | // deploy sale token 42 | const saleTokenFactory = await hre.ethers.getContractFactory("XavaToken"); 43 | const saleToken = await saleTokenFactory.deploy("Test Token 7", "TT7", "1000000000000000000000000000", 18); 44 | await saleToken.deployed(); 45 | console.log(` - Sale token deployed to: ${greenOut(saleToken.address)}`); 46 | 47 | // compute the states for a new sale 48 | // token amount & pricing 49 | const tokenPriceInAvax = ethers.utils.parseEther("0.00005").toString(); 50 | const totalTokens = ethers.utils.parseEther("1000000").toString(); 51 | const tokenPriceInUSD = 100000; // Six decimals USD value (100000 => 0.1$) 52 | // fundamental timestamps 53 | const registrationStart = await getCurrentBlockTimestamp() + 60; 54 | const registrationEnd = registrationStart + 3600; 55 | const validatorRound = registrationEnd + 60; 56 | const stakingRound = validatorRound + 180; 57 | const boosterRound = stakingRound + 600; 58 | const saleEndTime = boosterRound + 600; 59 | const tokensUnlockTime = saleEndTime + 600; 60 | // vesting 61 | const unlockingTimes = [tokensUnlockTime, tokensUnlockTime + 200, tokensUnlockTime + 400]; 62 | const percents = [3333, 3333, 3334]; 63 | const maxVestingTimeShift = 2592000; 64 | // dexalot 65 | const dexalotPortfolio = "0x780380eB4787775b07dfa60fB11C2CdAD6A44f7C"; 66 | const dexalotUnlockingTime = tokensUnlockTime - 300; 67 | // misc 68 | const portionVestingPrecision = 10000; 69 | const stakingRoundId = 2; 70 | const registrationDepositAVAX = ethers.utils.parseEther('1').toString(); 71 | 72 | // set proper sale parameters 73 | await(await sale.setSaleParams( 74 | saleToken.address, 75 | saleOwner, 76 | tokenPriceInAvax, 77 | totalTokens, 78 | saleEndTime, 79 | portionVestingPrecision, 80 | stakingRoundId, 81 | registrationDepositAVAX, 82 | tokenPriceInUSD 83 | )).wait(); 84 | console.log(' - Sale params set successfully.'); 85 | await delay(delayLength); 86 | 87 | // set sale registration time 88 | await sale.setRegistrationTime( 89 | registrationStart, 90 | registrationEnd 91 | ); 92 | console.log(' - Registration time set.'); 93 | await delay(delayLength); 94 | 95 | // set sale rounds 96 | await sale.setRounds( 97 | [validatorRound, stakingRound, boosterRound], 98 | [ethers.utils.parseEther('70000000'), 99 | ethers.utils.parseEther('70000000'), 100 | ethers.utils.parseEther('70000000')] 101 | ); 102 | console.log(' - Rounds set.'); 103 | await delay(delayLength); 104 | 105 | // set vesting parameters 106 | await sale.setVestingParams(unlockingTimes, percents, maxVestingTimeShift); 107 | console.log(' - Vesting parameters set successfully.'); 108 | await delay(delayLength); 109 | 110 | // deposit tokens to sale contract 111 | await saleToken.approve(sale.address, totalTokens); 112 | await delay(delayLength); 113 | await sale.depositTokens(); 114 | console.log(' - Tokens deposited.'); 115 | await delay(delayLength); 116 | 117 | // add dexalot portfolio support 118 | await sale.setAndSupportDexalotPortfolio(dexalotPortfolio, dexalotUnlockingTime); 119 | console.log(' - Dexalot Support Added.'); 120 | await delay(delayLength); 121 | 122 | await sale.setUpdateTokenPriceInAVAXParams(c['updateTokenPriceInAVAXPercentageThreshold'], c['updateTokenPriceInAVAXTimeLimit']); 123 | console.log(' - Token price updating parameters set.'); 124 | await delay(delayLength); 125 | 126 | console.log("Config:"); 127 | console.log({ 128 | saleAddress: lastDeployedSale, 129 | saleToken: saleToken.address, 130 | saleOwner, 131 | tokenPriceInAvax, 132 | tokenPriceInUSD, 133 | totalTokens, 134 | saleEndTime, 135 | tokensUnlockTime, 136 | registrationStart, 137 | registrationEnd, 138 | validatorRound, 139 | stakingRound, 140 | registrationDepositAVAX, 141 | unlockingTimes, 142 | percents, 143 | dexalotUnlockingTime 144 | }); 145 | 146 | const collateral = await hre.ethers.getContractAt("AvalaunchCollateral", contracts['AvalaunchCollateralProxy']); 147 | await collateral.approveSale(sale.address); 148 | console.log(' - Sale approved on collateral'); 149 | 150 | console.log(boldOut('Done!')); 151 | } 152 | 153 | main() 154 | .then(() => process.exit(0)) 155 | .catch(error => { 156 | console.error(error); 157 | process.exit(1); 158 | }); 159 | -------------------------------------------------------------------------------- /scripts/deployment/deploy_sales_staging_v2.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { getSavedContractAddresses, saveContractAddress } = require('../utils'); 3 | const { ethers } = hre; 4 | const { greenOut, boldOut } = require('../styling'); 5 | 6 | const getCurrentBlockTimestamp = async () => { 7 | return (await ethers.provider.getBlock('latest')).timestamp; 8 | } 9 | 10 | const delay = ms => new Promise(res => setTimeout(res, ms)); 11 | const delayLength = 3000; 12 | 13 | const main = async () => { 14 | 15 | const contracts = getSavedContractAddresses()[hre.network.name]; 16 | 17 | // instantiate salesFactory 18 | const salesFactory = await hre.ethers.getContractAt('SalesFactory', contracts['SalesFactory']); 19 | 20 | // deploy new sale and await the block after 21 | await(await salesFactory.deploySale()).wait(); 22 | console.log(boldOut('Sale deployed successfully.')); 23 | await delay(delayLength); 24 | 25 | // retrieve the sale deployed and save the address 26 | const lastDeployedSale = await salesFactory.getLastDeployedSale(); 27 | saveContractAddress(hre.network.name,'LatestSale', lastDeployedSale); 28 | console.log(`Deployed sale address: ${greenOut(lastDeployedSale)}`); 29 | console.log('Sub-operations:'); 30 | // instantiate deployed sale contract 31 | const sale = await hre.ethers.getContractAt('AvalaunchSaleV2', lastDeployedSale); 32 | console.log(' - Successfully instantiated sale contract.'); 33 | 34 | // deploy sale token 35 | const saleTokenFactory = await hre.ethers.getContractFactory("XavaToken"); 36 | const saleToken = await saleTokenFactory.deploy("Test Token", "TT", "1000000000000000000000000000", 18); 37 | await saleToken.deployed(); 38 | console.log(` - Sale token deployed to: ${greenOut(saleToken.address)}`); 39 | 40 | // compute the states for a new sale 41 | const saleEndTime = await getCurrentBlockTimestamp() + 3600 * 0.5; 42 | // token amount & pricing 43 | const tokenPriceInAvax = ethers.utils.parseEther("0.009").toString(); 44 | const totalTokens = ethers.utils.parseEther("1000000").toString(); 45 | // vesting 46 | const tokensUnlockTime = saleEndTime + 600; 47 | const unlockingTimes = [ 48 | tokensUnlockTime, 49 | tokensUnlockTime + 3600, 50 | tokensUnlockTime + 3600 * 2, 51 | tokensUnlockTime + 3600 * 3, 52 | tokensUnlockTime + 3600 * 4, 53 | tokensUnlockTime + 3600 * 5, 54 | tokensUnlockTime + 3600 * 6, 55 | tokensUnlockTime + 3600 * 7, 56 | tokensUnlockTime + 3600 * 8, 57 | tokensUnlockTime + 3600 * 9 58 | ]; 59 | const percents = [ 60 | 1000, 61 | 1000, 62 | 1000, 63 | 1000, 64 | 1000, 65 | 1000, 66 | 1000, 67 | 1000, 68 | 1000, 69 | 1000 70 | ]; 71 | // dexalot 72 | const dexalotPortfolio = "0x780380eB4787775b07dfa60fB11C2CdAD6A44f7C"; 73 | const dexalotUnlockingTime = saleEndTime + 300; 74 | // misc 75 | const portionVestingPrecision = 10000; 76 | const registrationDepositAVAX = ethers.utils.parseEther('1').toString(); 77 | 78 | // set proper sale parameters 79 | await(await sale.setSaleParams( 80 | saleToken.address, 81 | tokenPriceInAvax, 82 | totalTokens, 83 | saleEndTime, 84 | portionVestingPrecision, 85 | registrationDepositAVAX 86 | )).wait(); 87 | console.log(' - Sale params set successfully.'); 88 | await delay(delayLength); 89 | 90 | // set vesting parameters 91 | await sale.setVestingParams(unlockingTimes, percents); 92 | console.log(' - Vesting parameters set successfully.'); 93 | await delay(delayLength); 94 | 95 | // deposit tokens to sale contract 96 | await saleToken.approve(sale.address, totalTokens); 97 | await delay(delayLength); 98 | await sale.depositTokens(); 99 | console.log(' - Tokens deposited.'); 100 | await delay(delayLength); 101 | 102 | // add dexalot portfolio support 103 | await sale.setDexalotParameters(dexalotPortfolio, dexalotUnlockingTime); 104 | console.log(' - Dexalot Support Added.'); 105 | await delay(delayLength); 106 | 107 | console.log("Config:"); 108 | console.log({ 109 | saleAddress: lastDeployedSale, 110 | saleToken: saleToken.address, 111 | tokenPriceInAvax, 112 | totalTokens, 113 | saleEndTime, 114 | tokensUnlockTime, 115 | registrationDepositAVAX, 116 | unlockingTimes, 117 | percents, 118 | dexalotUnlockingTime 119 | }); 120 | 121 | const marketplace = await hre.ethers.getContractAt("AvalaunchMarketplace", contracts['AvalaunchMarketplaceProxy']); 122 | await marketplace.approveSale(sale.address); 123 | console.log(' - Sale approved on marketplace'); 124 | 125 | const collateral = await hre.ethers.getContractAt("AvalaunchCollateral", contracts['AvalaunchCollateralProxy']); 126 | await collateral.approveSale(sale.address); 127 | console.log(' - Sale approved on collateral'); 128 | 129 | console.log(boldOut('Done!')); 130 | } 131 | 132 | main() 133 | .then(() => process.exit(0)) 134 | .catch(error => { 135 | console.error(error); 136 | process.exit(1); 137 | }); 138 | -------------------------------------------------------------------------------- /scripts/deployment/deploy_sales_v2.js: -------------------------------------------------------------------------------- 1 | const { ethers, network } = require("hardhat"); 2 | const { getSavedContractAddresses, saveContractAddress } = require('../utils'); 3 | const { greenOut, boldOut } = require('../styling'); 4 | const config = require("../configs/saleConfig.json"); 5 | 6 | const delay = ms => new Promise(res => setTimeout(res, ms)); 7 | const delayLength = 3000; 8 | 9 | const main = async () => { 10 | 11 | const contracts = getSavedContractAddresses()[network.name]; 12 | const c = config[network.name]; 13 | 14 | // instantiate salesFactory 15 | const salesFactory = await ethers.getContractAt('SalesFactory', contracts['SalesFactory']); 16 | 17 | // deploy new sale and await the block after 18 | await (await salesFactory.deploySale()).wait(); 19 | console.log(boldOut('Sale deployed successfully.')); 20 | 21 | await delay(delayLength); 22 | 23 | // retrieve the sale deployed and save the address 24 | const lastDeployedSale = await salesFactory.getLastDeployedSale(); 25 | saveContractAddress(network.name, c['saleName'], lastDeployedSale); 26 | console.log(`Deployed sale address: ${greenOut(lastDeployedSale)}`); 27 | 28 | console.log('Sale setup:'); 29 | // instantiate deployed sale contract 30 | const sale = await ethers.getContractAt('AvalaunchSaleV2', lastDeployedSale); 31 | console.log(' - Successfully instantiated sale contract.'); 32 | 33 | // compute the states for a new sale 34 | const saleEndTime = c['saleEndTime']; 35 | const token = c['tokenAddress']; 36 | const registrationDepositAVAX = ethers.utils.parseEther(c['registrationDepositAVAX']); 37 | // token amount & pricing 38 | const tokenPriceInAvax = ethers.utils.parseEther(c['tokenPriceInAvax']); 39 | const totalTokens = ethers.utils.parseEther(c['totalTokens']); 40 | // vesting 41 | const portionVestingPrecision = c['portionVestingPrecision']; 42 | const unlockingTimes = c['unlockingTimes']; 43 | const percents = c['portionPercents']; 44 | 45 | // set proper sale parameters 46 | await(await sale.setSaleParams( 47 | token, 48 | tokenPriceInAvax, 49 | totalTokens, 50 | saleEndTime, 51 | portionVestingPrecision, 52 | registrationDepositAVAX 53 | )).wait(); 54 | console.log(' - Sale params set successfully.'); 55 | await delay(delayLength); 56 | 57 | // set vesting parameters 58 | await sale.setVestingParams(unlockingTimes, percents); 59 | console.log(' - Vesting parameters set successfully.'); 60 | await delay(delayLength); 61 | 62 | // // add dexalot portfolio support 63 | // await sale.setAndSupportDexalotPortfolio(c['dexalotPortfolio'], c['dexalotUnlockingTime']) 64 | // .then(() => console.log(greenOut('Dexalot supported.'))) 65 | // .catch((err) => console.log(redOut('Dexalot not supported.'))); 66 | 67 | console.log("Config:"); 68 | console.log({ 69 | sale: lastDeployedSale, 70 | token, 71 | tokenPriceInAvax, 72 | totalTokens, 73 | saleEndTime, 74 | registrationDepositAVAX, 75 | unlockingTimes, 76 | percents 77 | }); 78 | 79 | const marketplace = await ethers.getContractAt("AvalaunchMarketplace", contracts['AvalaunchMarketplaceProxy']); 80 | await marketplace.approveSale(sale.address) 81 | .then(() => console.log(' - Sale approved on marketplace')) 82 | .catch((err) => console.log(' - Marketplace whitelist failed.')); 83 | 84 | 85 | const collateral = await ethers.getContractAt("AvalaunchCollateral", contracts['AvalaunchCollateralProxy']); 86 | await collateral.approveSale(sale.address) 87 | .then(() => console.log(' - Sale approved on collateral')) 88 | .catch((err) => console.log(' - Collateral whitelist failed.')); 89 | 90 | console.log(boldOut('Done!')); 91 | } 92 | 93 | main() 94 | .then(() => process.exit(0)) 95 | .catch(error => { 96 | console.error(error); 97 | process.exit(1); 98 | }); 99 | -------------------------------------------------------------------------------- /scripts/deployment/deploy_singletons.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { saveContractAddress, getSavedContractAddresses } = require('../utils') 3 | const config = require('../configs/config.json'); 4 | 5 | async function getCurrentBlockTimestamp() { 6 | return (await ethers.provider.getBlock('latest')).timestamp; 7 | } 8 | 9 | async function main() { 10 | 11 | const c = config[hre.network.name]; 12 | const contracts = getSavedContractAddresses()[hre.network.name]; 13 | 14 | const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; 15 | 16 | 17 | const Admin = await ethers.getContractFactory("Admin"); 18 | const admin = await Admin.deploy(c.admins); 19 | await admin.deployed(); 20 | console.log("Admin contract deployed to: ", admin.address); 21 | saveContractAddress(hre.network.name, "Admin", admin.address); 22 | 23 | 24 | const SalesFactory = await ethers.getContractFactory("SalesFactory"); 25 | const salesFactory = await SalesFactory.deploy(admin.address, ZERO_ADDRESS); 26 | await salesFactory.deployed(); 27 | saveContractAddress(hre.network.name, "SalesFactory", salesFactory.address); 28 | console.log('Sales factory deployed to: ',salesFactory.address); 29 | 30 | const currentTimestamp = await getCurrentBlockTimestamp(); 31 | console.log('Farming starts at: ', currentTimestamp); 32 | 33 | const AllocationStaking = await ethers.getContractFactory("AllocationStaking"); 34 | const allocationStaking = await upgrades.deployProxy(AllocationStaking, [ 35 | contracts["XavaToken"], 36 | ethers.utils.parseEther(c.allocationStakingRPS), 37 | currentTimestamp + c.delayBeforeStart, 38 | salesFactory.address, 39 | c.depositFeePercent, 40 | c.depositFeePrecision 41 | ], { unsafeAllow: ['delegatecall'] } 42 | ); 43 | await allocationStaking.deployed() 44 | console.log('AllocationStaking Proxy deployed to:', allocationStaking.address); 45 | saveContractAddress(hre.network.name, 'AllocationStaking', allocationStaking.address); 46 | 47 | let proxyAdminContract = await upgrades.admin.getInstance(); 48 | saveContractAddress(hre.network.name, 'ProxyAdmin', proxyAdminContract.address); 49 | console.log('Proxy Admin address is : ', proxyAdminContract.address); 50 | 51 | await salesFactory.setAllocationStaking(allocationStaking.address); 52 | console.log(`salesFactory.setAllocationStaking ${allocationStaking.address} done.;`); 53 | 54 | const totalRewards = ethers.utils.parseEther(c.initialRewardsAllocationStaking); 55 | 56 | const token = await hre.ethers.getContractAt('XavaToken', contracts['XavaToken']); 57 | const devToken = await hre.ethers.getContractAt('DevToken', contracts['DevTokenAlloStaking']); 58 | 59 | await token.approve(allocationStaking.address, totalRewards); 60 | console.log(`token.approve(${allocationStaking.address}, ${totalRewards.toString()});`) 61 | 62 | await allocationStaking.add(c.xavaPoolAllocPoints, token.address, true); 63 | console.log(`allocationStaking.add(${c.xavaPoolAllocPoints}, ${token.address}, true);`) 64 | 65 | await allocationStaking.add(c.placeholderPoolAllocPoints, contracts["DevTokenAlloStaking"], true); 66 | console.log(`allocationStaking.add(${c.placeholderPoolAllocPoints}, ${contracts["DevTokenAlloStaking"]}, true)`) 67 | 68 | // Fund only 5000 tokens, for testing 69 | await allocationStaking.fund(ethers.utils.parseEther('50000')); 70 | console.log('Funded tokens') 71 | 72 | const totalSupplyDevToken = ethers.utils.parseEther('10000'); 73 | await devToken.approve(allocationStaking.address, totalSupplyDevToken); 74 | console.log('Dev token successfully approved.'); 75 | } 76 | 77 | 78 | main() 79 | .then(() => process.exit(0)) 80 | .catch(error => { 81 | console.error(error); 82 | process.exit(1); 83 | }); 84 | -------------------------------------------------------------------------------- /scripts/deployment/deploy_token.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { saveContractAddress } = require('../utils') 3 | 4 | async function main() { 5 | const tokenName = "Avalaunch"; 6 | const symbol = "XAVA"; 7 | const totalSupply = "100000000000000000000000000"; 8 | const decimals = 18; 9 | 10 | const XavaToken = await hre.ethers.getContractFactory("XavaToken"); 11 | const token = await XavaToken.deploy(tokenName, symbol, totalSupply, decimals); 12 | await token.deployed(); 13 | console.log("Xava Token deployed to: ", token.address); 14 | 15 | saveContractAddress(hre.network.name, "XavaToken", token.address); 16 | } 17 | 18 | 19 | main() 20 | .then(() => process.exit(0)) 21 | .catch(error => { 22 | console.error(error); 23 | process.exit(1); 24 | }); 25 | -------------------------------------------------------------------------------- /scripts/deployment/deploy_vesting_private.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { getSavedContractAddresses, saveContractAddress } = require('../utils') 3 | const config = require('../configs/config.json'); 4 | 5 | const delay = ms => new Promise(res => setTimeout(res, ms)); 6 | 7 | 8 | async function main() { 9 | 10 | await hre.run('compile') 11 | 12 | const ParticipationVestingPrivate = await hre.ethers.getContractFactory('ParticipationVestingPrivate'); 13 | 14 | const participationVestingContract = await ParticipationVestingPrivate.deploy( 15 | config[hre.network.name].numberOfPortions, 16 | config[hre.network.name].timeBetweenPortions, 17 | config[hre.network.name].distributionStartDate, 18 | config[hre.network.name].firstPortionUnlock, 19 | config[hre.network.name].adminWallet, 20 | getSavedContractAddresses()[hre.network.name]["XavaToken"] 21 | ); 22 | 23 | await participationVestingContract.deployed(); 24 | console.log("Participation Vesting Private contract deployed to: ", participationVestingContract.address); 25 | saveContractAddress(hre.network.name, 'ParticipationVestingPrivate', participationVestingContract.address); 26 | } 27 | 28 | 29 | main() 30 | .then(() => process.exit(0)) 31 | .catch(error => { 32 | console.error(error); 33 | process.exit(1); 34 | }); 35 | -------------------------------------------------------------------------------- /scripts/deployment/deploy_vesting_seed.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { getSavedContractAddresses, saveContractAddress } = require('../utils') 3 | const config = require('../configs/config.json'); 4 | 5 | const delay = ms => new Promise(res => setTimeout(res, ms)); 6 | 7 | 8 | async function main() { 9 | 10 | await hre.run('compile') 11 | 12 | const ParticipationVestingSeed = await hre.ethers.getContractFactory('ParticipationVestingSeed'); 13 | 14 | const participationVestingContract = await ParticipationVestingSeed.deploy( 15 | config[hre.network.name].numberOfPortions, 16 | config[hre.network.name].timeBetweenPortions, 17 | config[hre.network.name].distributionStartDate, 18 | config[hre.network.name].firstPortionUnlock, 19 | config[hre.network.name].adminWallet, 20 | getSavedContractAddresses()[hre.network.name]["XavaToken"] 21 | ); 22 | 23 | await participationVestingContract.deployed(); 24 | console.log("Participation Vesting Seed contract deployed to: ", participationVestingContract.address); 25 | saveContractAddress(hre.network.name, 'ParticipationVestingSeed', participationVestingContract.address); 26 | 27 | const seed = [ 28 | "0xe90950A1B7Ad930d2dfBb3A4cDFD54669dE06B3e", 29 | "0x2821E2DEcE4150649096644686baac3A73607f46", 30 | "0x5e08bf95DcDd45B17963DbB7F9271Bb4a8A49194", 31 | "0xf019675Ce68fe13089EeA5DABDC743c1a1155C0e", 32 | "0x1D893D40d13254F86becC73ba3f15cA21e9F1A76", 33 | "0x7B17a951B040644318AD2FFF3F47C9348fF854Cd", 34 | "0x3A9103378E96CD9179c5fD226044d1e2936d7A59", 35 | "0x205ecb4dbEf2eC61D6F1B92c4276Cdd7929F503d", 36 | "0x99D1d7890bfC58Df34eaCA892dFde98Fa6118c44", 37 | "0x8233484c7648f59086CeEA05f0A8D6a976CdAa75", 38 | "0xa97e743fC09861a4AB3b38cB7a8F64BDF24EbeaC", 39 | "0x6167FF49E5F873a5Aeae485dbc1B6f03d8F82bFC", 40 | "0x773a1FD0f9D8048B0fd24e234feD69495C0fa15b", 41 | "0x737dE5e58835A7CEfBE3de73f443c885cD245BCb", 42 | "0x54b5f900014Ed1B842cDb79672b732A21f134fa8", 43 | "0xe1bAf2857197C89CF7E2738E90beFe2FbB838Ce7" 44 | ]; 45 | 46 | const seedAmounts = [ 47 | '1250000000000000000000000', 48 | '750000000000000000000000', 49 | '500000000000000000000000', 50 | '1250000000000000000000000', 51 | '1000000000000000000000000', 52 | '750000000000000000000000', 53 | '500000000000000000000000', 54 | '500000000000000000000000', 55 | '1250000000000000000000000', 56 | '1250000000000000000000000', 57 | '750000000000000000000000', 58 | '750000000000000000000000', 59 | '1000000000000000000000000', 60 | '500000000000000000000000', 61 | '1000000000000000000000000', 62 | '1025000000000000000000000' 63 | ]; 64 | 65 | const totalTokens = '14025000000000000000000000'; 66 | 67 | let token = await hre.ethers.getContractAt('XavaToken', getSavedContractAddresses()[hre.network.name]["XavaToken"]); 68 | await token.transfer(participationVestingContract.address, totalTokens); 69 | console.log('Transfer done'); 70 | 71 | await participationVestingContract.registerParticipants( 72 | seed, 73 | seedAmounts 74 | ); 75 | } 76 | 77 | 78 | main() 79 | .then(() => process.exit(0)) 80 | .catch(error => { 81 | console.error(error); 82 | process.exit(1); 83 | }); 84 | -------------------------------------------------------------------------------- /scripts/distribution/distributeAVAX.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { getSavedContractAddresses } = require('../utils') 3 | const { ethers, web3 } = hre 4 | 5 | 6 | 7 | async function main() { 8 | 9 | const contracts = getSavedContractAddresses()[hre.network.name]; 10 | 11 | const wallets = [ 12 | "0xfAc9a12C61Fd8784F115c53bF9d6dbd502F07e34","0xf89676d1443B2867d9221066Ed853F1ff281f9F2","0xbEb78f0B3f39e3f3Fc59838a860B2C5b45561d4F","0x464cCB46f2D12950667DdA4025a420DCa7066C3d","0xf7d3168f0cb6F64C284dEA2eEFE72b3D497a525D","0x9E092Bfdf8854179562B3d8F63e00B4C9feDF10a","0x166A0E0DF66Ca33cCc3B97bD83f692Cf83fBd420","0x4ebEE2a376E2dBD0BEb49128aE00D66c98a14f55","0xEfcE847D41Ebe1Ced1b7C7212Ce2ea239855a6E1","0x36eAb166cb30E30cBC7dF6071C224fdc9dC4d34F","0x7e9B1AB31a5f7FF1c89DCcB39Bc6760946e2c618","0x93d9b6C68330eE19356052562fAf3781b055CE12","0x3c5843a32920dA42934b0d52aA0f5980da2f3B54","0x4Da07a1ac19abc476B47369b10f0992a53313C15","0x680BCf08c59B70FB3Ac6225C0dc768c0DB8248dA","0x66D26242f67e25966dB209e998fcAC0dEbA48899","0x46F8779cBD8e3Ef132fFa3AA1cfc3CAC17437D20","0xBa0149Bfb19C4B0809AE263B564F2E289331c36B","0x6B2A68888E3EE39F61ec7774503C9585405B5740","0xbBd4a5F1D40C437C6015079d3e4063c04666486e","0x99a5Dc7b00F58419285Eb0cD3D447f5dA552d2d9","0xBcaef30dF7f6c103E1E54eA6df77A2DD62c3D33E","0x2abAE08416bcF2B61D9D15285F043e28de7F3E38","0x9231546A0e1F2773Ea6B0f30c691EA56E5fE2D24","0x48DfF8dF421c208343804579a90a2cB360f145dd","0x8F09D3f2F551C8c7b4C1A04aE1E46F01D2afC99c","0x1C2bae45d79c8FF7F499E2d67796E4d34a786B12","0x58A4E7dC8a13d18d3Bb59bE365982b7641B64A28","0x05E9d3b044bf812C6845f33FabfFF0509C3290c7","0xCA4477d2E813eDb32119A444D468B3FFAa97434b","0xFC7520d435d3296791571A60fa6125C58678091B","0xc6c2bD6B76Bf5F1Fb63DF95c42F36745F83c6702","0x519D5fBA523cf4Fa844d28524AC93d80c9c493D2","0xea99552aF03140457Ec1a989C8A7e9C5854093E9","0xbDB0785E7fC8aF47Be498646226cb8efdE53fB1a","0x0a7bf04d5bfB336daf7a1F44e89DBa17Fd9b3DcA","0x91CA96f95e3f352036E5cC0199A9df410CA3F10a","0xB20807E62E6fEa9EccE55bd30D42CaE6747BEe58","0x71308b70B56841F48C0Ef9C8b29d1E2e5C2b3157","0xe9256C5cDdb8a4B1B1cE49AeBE8af8c3e531543A","0x6B90ABcD35BB0E3977bCb2D6f992d6303fa4f927","0x6B2362c1ba180C22C2558529924013ae3C7dfCA7","0xf5aF2c1E38Efb3106D3895EbD6200AaE8F65832e","0xceC651634796E6f4783b6C216854ffD9c0CAbA7F","0x8E02fe775433a704216f5cbb0e0835F3dbeF8e82","0x08A6058776D0a0c6ADb2610e16eE199453E707D5","0xfEC0180f81850b376B5210F0Ee0BE529a26E22cE","0x74B3e9a2B66c64C3F8f1e2Ca2009A7CD334139B5","0x78a8447e3aB52BdeC9af409c0ad3d5BB4c27C4Cb","0xeace2AB1c530a4e427df283cAB959FD486997Fcd","0x8a7d89142023Db7c71221BABEA45081AB697F3dA","0x34569008B34DEdBF41BC9dbCC5d7AAbe6eB7E596","0xe3756018b41F19777BEa4e04C894acB5eD352D77","0x5990496F386ae8E75384933bC3E0229B62203311","0x7fa55C921C8Cf5def22243f8BB4B37D8DF7d7883","0x74C76cfA6f0ee807880b5C18A07F81A8761F856a","0x6BcCaCFbCaAc44bd84E52A844E9B30eAb40Ad4BB","0x9da5C4C283c2Fe334E2a1081A7fdae45475CeB41","0xe61E92dd9a7f7C0Af544606ac10D52F8fcE30f78","0x15870AF7A292aD698827182Fdd11b083298A9990","0x21A8652b81adb2420477Ccd3D156002E43D1BbD3","0xEECb16afB8bDde10bC540436188c4b441d75968b","0xF931CC9Cc114949b81245261C04BcC6DDb12ed8A","0xd80Ef49A7c64F8217343582b417031A5B359e1d0","0xFcCA7C390767b347549e3D2242dd8d30be925c28","0x1b1813F8993a5a21d6914c7b9375eb908a689080","0xdb0131A53EC1687c002950Ad9D66a9B983864276","0x4195B59E5De08CF9Fbf81aD9FC14E8812393135B","0xCD7ebeC46A35fd1e0CaDC367202343e67Ac7C562","0x21f22F1f7E1051C0C73CBBD0f72DB0842897C92F","0x9939197Ab41daaD7D9Be323CFC60059044C16630","0x1c19B1e9f19000aE615f762fF801C076F1DEa527","0xf25a82A7089b47c278EFB94D78CaC13aAc99867b","0x80b192e32Fa95EEfd3b076fB50519De41bFD0e5C","0xDA5Dd209717Ef264908C1181CaDc9bcE9CB19a46","0xe72EEb49B4805ba2910c57982F9353377Fa6F466","0xC1B0e8983B8cD4A5f120D5F14f38Ee8Da5312112","0x48e472D6978b8707C6C81e4Ff976B24F4Df33907","0x41Daf06CB0cB9290E698000E15820f75139b5b36","0x24Ca1771Fe1E7a0e047f22644113c6E8aD21f991","0xb00126BFa30B08014CCc63589b0E8eF0F54799Ee","0xFB999EF7d317fedc4c0F824a8Ba6BA25922E6d72","0xa4589d0E777A18E3148859bFb031465aF135df34","0xD40f0D07B9068F32843c8AE1Da38f71e380bCc74","0x75590093A908d2D413d3caE8c670C13f380668d6","0xe8241Ad35D8285965D401E23fA9dC1F6737C1CCc","0xB726Ae8dB84774f926Bf5Fbb399CfbE3f102F0D0","0x054A51a7DD8ECf12a83640fd7e25f16c777Cd8Fc","0x5b1c38BFeBC1D71a991D0Cc4f0772DB25F6365e7","0x18C6c577f3363a414aF7e2518fb9cf070EBaC76A","0x7EC31DFa3e0318D4B71344A34Dd9D51bbEc79724","0xF6aD92aF1E2Cd832dF3eEbCea2e201b00b9D71Ce","0xFF0c80920f69A5D1d8F913065642Af45E8CBadA7","0x82CfCB40c62803e27779BF1c6c83b86B2f29019A","0x7E71818e890C1B35De95A0a854D882CcD2E7E996","0x01c702bEb4270EA0be63a52610C85E63e91d2F4C","0x7e2a3b38Dc783F852360d73962C604B4b875eD07","0xF8e88100c8Dc5d6229e147561384a1289b33Edef","0xB400Dc972b08FB728CFc7373386E9d5f1125957A","0x699fB49a635306249777a66E9eD5CdD357a4607c","0x85a139E8932e0C5CD5314bBDa0E26e07B708fd8E","0x7df7b4dd91a5Ae73C95c9c96511dadb127e9bbe2","0x13Db4917a17905e4ee65C1452aE85b36d4d7C8Dd","0x6b84036e7E4ac6d11da923DF00B95897D1593deb","0x00131601ac5e26219038056144e0b055deA37075","0xd9be17980F1206B4F88240234429Ecc86EE620a6","0x77FE310e8b9e0709D93742bb76Df6a28dab5a333","0x1555e776C4BfA56581B71A58d92D7969720E27EC","0x9c868F3299E212B46E6E96B951B5A7a17Bff3940","0xf2406dFcb1b48D8772E748A62aC7528aCcE81A42","0xA7753aE84E23b6720F1A4bf104f3E7B93d730ACC","0xd6A8766D1A947FaBCB028Cb65486Bbc676A499Bc","0x9dd6D33dcC532D1278e655c4001E064ac257B2c2","0x25a4aE48B07bDB20dBf806F2acb9571A5a5C5598","0xe60996DDb83aC3cE81Cf5DA92740461a9F3A65f6","0x8511506c03b36BA1A70cF96Fc2Ebe8E52F3c9Bd7","0x2eec1678f7eEb2f0bd41446aea83689D756e5087" 13 | ]; 14 | const amountETH = "0.1"; 15 | 16 | console.log('Number of wallets to receive AVAX = ', wallets.length); 17 | 18 | for (let i=0; i < wallets.length; i++) { 19 | 20 | const signer = await ethers.provider.getSigner(); 21 | const address = await signer.getAddress(); 22 | 23 | const tx = await signer.sendTransaction({ 24 | to: ethers.provider._getAddress(wallets[i]), 25 | value: ethers.utils.parseEther(amountETH) 26 | }); 27 | 28 | console.log(`${i+1}. TxHash: ${tx.hash}`); 29 | console.log(`${i+1}. Receiver: ${wallets[i]}`); 30 | console.log('--------------------------------------------------------------------------------'); 31 | } 32 | 33 | } 34 | 35 | 36 | main() 37 | .then(() => process.exit(0)) 38 | .catch(error => { 39 | console.error(error); 40 | process.exit(1); 41 | }); 42 | -------------------------------------------------------------------------------- /scripts/distribution/distributeXAVA.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { saveContractAddress, getSavedContractAddresses } = require('../utils') 3 | const { ethers, web3 } = hre 4 | 5 | async function getCurrentBlockTimestamp() { 6 | return (await ethers.provider.getBlock('latest')).timestamp; 7 | } 8 | 9 | async function main() { 10 | 11 | const contracts = getSavedContractAddresses()[hre.network.name]; 12 | 13 | const wallets = [ 14 | '0x6818eDffA6367e7EE365047BB711AF2E180e9dD3', 15 | '0x67A776Ce18c5E71abb01273A2971E32469F5Bbe1', 16 | '0xB4c92006CeFE40E0BFD57cee81A3A95b06Ffa5ff', 17 | '0x8408656B59758f1bb8dec232C5F62eE7Bfa9A017', 18 | '0xA4fF8f36E5bD5b1Df9f1Fe261bd68F45db1a1b9E', 19 | '0x5DE5BDaF5F673bd01D91379b0Fc9386E41F0B177', 20 | '0x5E1c8C3E8a256F414b4731CC11B796cBc10c7d00', 21 | '0x7b72Fcc48fF3e534659b74d95b57141E1174Fb59', 22 | '0xd98b7EC2CF985EdFF3959DE5De5a4bc1F151D70A', 23 | '0xA57e3dDE79298aDe6d2Ca66032Bd7D636E2387A2', 24 | '0x25f1c595cd8aA9a9E1eb16AC970b94e13637f1f0', 25 | '0x339cf62CB6a2E4F87eB1B6b3661F3f6c3a130328', 26 | '0xc86C61654f3176fDe88963Fc62EbE73324E04412', 27 | '0x49760D434FE42CB0379EDc5D04Fbbe3909ACc482', 28 | '0x410C62978a8784709906A084834a71E07e9572D4', 29 | '0xAf4Dff2bA4234f02bFe187EC55eB58b6bFa630E5', 30 | '0x76B9E19EBA8e4cD90dd46E642D642813723d626E', 31 | '0x7Fb3D0b92ADF411b3BC1aaDAe0670eA641b0b9Bc', 32 | '0xC8Ea6fB14D82F88a8A5075774571d1D4cd1AF00E', 33 | '0xfB42e80921013200413DeccdBA07C30A39B9D17E', 34 | '0x9218E2b14A09Cf707a2980f303B967eeE0BC3890', 35 | '0x0B8eFD8174398222d3F922eb6EbE9375d71C23De', 36 | '0xf001d3fe81F45Cc47e6cd94c8eA130dDD128a68f', 37 | '0x98873638a695dc8b5443BdfC704191387d788C9D', 38 | '0x306A7750f0A861214A4f1413822b6F3A12767E89', 39 | '0x6d1C24cFC33e2df39223e6bd4d7FA000e3cCA450' 40 | ]; 41 | 42 | console.log('Wallets to receive: ', wallets.length); 43 | 44 | const amount = ethers.utils.parseEther('10'); 45 | 46 | const token = await hre.ethers.getContractAt('XavaToken', '0xd1c3f94DE7e5B45fa4eDBBA472491a9f4B166FC4'); 47 | const symbol = await token.symbol(); 48 | 49 | for (let i=0; i < wallets.length; i++) { 50 | let resp = await token.transfer( 51 | wallets[i], 52 | amount 53 | ); 54 | console.log(`${i+1}: Done. Sent 10 ${symbol} to: ${wallets[i]}`); 55 | console.log(`${i+1}: TxHash:`, resp.hash); 56 | } 57 | } 58 | 59 | 60 | main() 61 | .then(() => process.exit(0)) 62 | .catch(error => { 63 | console.error(error); 64 | process.exit(1); 65 | }); 66 | -------------------------------------------------------------------------------- /scripts/getters.js: -------------------------------------------------------------------------------- 1 | // scripts/upgrade-box.js 2 | const { ethers, upgrades } = require("hardhat"); 3 | const { getSavedContractAddresses } = require('./utils') 4 | const hre = require("hardhat"); 5 | 6 | async function getCurrentBlockTimestamp() { 7 | return (await ethers.provider.getBlock('latest')).timestamp; 8 | } 9 | 10 | async function main() { 11 | const contracts = getSavedContractAddresses()[hre.network.name]; 12 | const allocationStaking = await hre.ethers.getContractAt( 13 | 'AllocationStaking', 14 | contracts['AllocationStakingProxy'] 15 | ); 16 | 17 | const unlockTime = await getCurrentBlockTimestamp(); 18 | 19 | const stake = await allocationStaking.deposited(0, '0xE8E6959a29bB94cB1080DE4257417E6f22AB3AE2'); 20 | console.log(stake.toString()); 21 | 22 | const fee = await allocationStaking.getWithdrawFee('0xE8E6959a29bB94cB1080DE4257417E6f22AB3AE2', stake.toString(), 0); 23 | console.log(fee.toString()); 24 | 25 | const endDate = await allocationStaking.setTokensUnlockAtForUser( 26 | '0xE8E6959a29bB94cB1080DE4257417E6f22AB3AE2', 27 | 0, 28 | unlockTime 29 | ); 30 | 31 | } 32 | 33 | 34 | main() 35 | .then(() => process.exit(0)) 36 | .catch(error => { 37 | console.error(error); 38 | process.exit(1); 39 | }); 40 | -------------------------------------------------------------------------------- /scripts/prolongue_farm.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { getSavedContractAddresses } = require('./utils') 3 | const { ethers, web3 } = hre 4 | 5 | async function main() { 6 | const contracts = getSavedContractAddresses()[hre.network.name]; 7 | 8 | const rewardsToAdd = ethers.utils.parseEther("50000"); 9 | 10 | // Get instance of Farm V2 11 | const farm = await hre.ethers.getContractAt('FarmingXava', contracts['FarmingXavaV2']); 12 | const token = await hre.ethers.getContractAt('XavaToken', contracts['XavaToken']); 13 | 14 | // Approve Farm to take tokens 15 | await token.approve(farm.address, rewardsToAdd); 16 | console.log('Approved Farm to take tokens.'); 17 | 18 | await farm.fund(rewardsToAdd); 19 | console.log('Farm fulfilled with more rewards.'); 20 | } 21 | 22 | // We recommend this pattern to be able to use async/await everywhere 23 | // and properly handle errors. 24 | main() 25 | .then(() => process.exit(0)) 26 | .catch(error => { 27 | console.error(error); 28 | process.exit(1); 29 | }); 30 | -------------------------------------------------------------------------------- /scripts/saleChecksum.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { saveContractAddress, getSavedContractAddresses } = require('./utils') 3 | const config = require("./configs/saleConfig.json"); 4 | const {BigNumber} = require("ethers"); 5 | 6 | // Style 7 | const bS = "\x1b[1m"; // Brightness start 8 | const e = "\x1b[0m"; // End style 9 | const VALID = bS + "\x1b[32mVALID ✅" + e; 10 | const NOT_VALID = bS + "\x1b[31mNOT VALID ❌" + e; 11 | 12 | const NUMBER_1E18 = "1000000000000000000"; 13 | 14 | async function main() { 15 | const c = config[hre.network.name]; 16 | 17 | const saleAddress = '0x0450CFD41a9bbA5349f50a75043d69e8D96f2f9e'; 18 | 19 | const saleContract = await hre.ethers.getContractAt('AvalaunchSale', saleAddress); 20 | 21 | const sale = await saleContract.sale(); 22 | const registration = await saleContract.registration(); 23 | 24 | console.log('Token'); 25 | console.log(sale[0], c["tokenAddress"], sale[0] === c["tokenAddress"] ? VALID : NOT_VALID, "\n"); 26 | 27 | console.log("SaleOwner"); 28 | console.log(sale[5], c["saleOwner"], sale[5] === c["saleOwner"] ? VALID : NOT_VALID, "\n"); 29 | 30 | console.log("RegistrationDepositAvax"); 31 | const regDep = await saleContract.registrationDepositAVAX(); 32 | console.log( 33 | parseInt(regDep.div(NUMBER_1E18)).toString(), c["registrationDepositAVAX"], 34 | parseInt(regDep.div(NUMBER_1E18)).toString() === c["registrationDepositAVAX"] ? VALID : NOT_VALID, "\n" 35 | ); 36 | 37 | console.log("TotalTokenAmount") 38 | const totalTokens = sale[7]; 39 | const a = c["totalTokens"]; 40 | console.log( 41 | parseInt(totalTokens), parseInt(BigNumber.from(a).mul(NUMBER_1E18)), 42 | parseInt(totalTokens) === parseInt(BigNumber.from(a).mul(NUMBER_1E18)) ? VALID : NOT_VALID, "\n" 43 | ); 44 | 45 | console.log("TokenPriceInAvax") 46 | const o = sale[6]; 47 | const p = parseFloat(c["tokenPriceInAvax"]) * NUMBER_1E18; 48 | console.log( 49 | parseInt(o), parseInt(p), 50 | parseInt(o) === parseInt(p) ? VALID : NOT_VALID, "\n" 51 | ); 52 | 53 | console.log("Sale end"); 54 | let val1 = parseInt(sale[10]); 55 | let val2 = parseInt(c["registrationStartAt"]) + parseInt(c["registrationLength"]) + 56 | parseInt(c["delayBetweenRegistrationAndSale"]) + parseInt(c["validatorRoundLength"]) + 57 | parseInt(c["stakingRoundLength"]) + parseInt(c["boosterRoundLength"]); 58 | 59 | console.log(val1, val2, val1 === val2 ? VALID : NOT_VALID, "\n"); 60 | 61 | // console.log("TokensUnlockTime") 62 | // val1 = parseInt(sale[10]); 63 | // val2 = parseInt(c["unlockingTimes"][0]); 64 | // console.log(val1, val2, val1 === val2 ? VALID : NOT_VALID, "\n"); 65 | 66 | console.log("Registration Start"); 67 | val1 = parseInt(registration[0]); 68 | val2 = parseInt(c["registrationStartAt"]); 69 | console.log(val1, val2, val1 === val2 ? VALID : NOT_VALID, "\n"); 70 | 71 | console.log("Registration End"); 72 | val1 = parseInt(registration[1]); 73 | val2 = parseInt(c["registrationStartAt"]) + parseInt(c["registrationLength"]); 74 | console.log(val1, val2, val1 === val2 ? VALID : NOT_VALID, "\n"); 75 | 76 | console.log("Validator Round Start"); 77 | const round1 = await saleContract.roundIdToRound(1); 78 | val1 = parseInt(round1[0]); 79 | val2 = parseInt(c["registrationStartAt"]) + parseInt(c["registrationLength"]) + 80 | parseInt(c["delayBetweenRegistrationAndSale"]); 81 | console.log(val1, val2, val1 === val2 ? VALID : NOT_VALID, "\n"); 82 | 83 | console.log("Staking Round Start"); 84 | const round2 = await saleContract.roundIdToRound(2); 85 | val1 = parseInt(round2[0]); 86 | val2 = parseInt(c["registrationStartAt"]) + parseInt(c["registrationLength"]) + 87 | parseInt(c["delayBetweenRegistrationAndSale"]) + parseInt(c["validatorRoundLength"]); 88 | console.log(val1, val2, val1 === val2 ? VALID : NOT_VALID, "\n"); 89 | } 90 | 91 | main() 92 | .then(() => process.exit(0)) 93 | .catch(error => { 94 | console.error(error); 95 | process.exit(1); 96 | }); 97 | -------------------------------------------------------------------------------- /scripts/saveABi.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { saveContractAbi } = require('./utils'); 3 | 4 | 5 | async function main() { 6 | await hre.run('compile'); 7 | 8 | saveContractAbi(hre.network.name, 'Admin', (await hre.artifacts.readArtifact("Admin")).abi) 9 | saveContractAbi(hre.network.name, 'SalesFactory', (await hre.artifacts.readArtifact("SalesFactory")).abi) 10 | saveContractAbi(hre.network.name, 'AllocationStaking', (await hre.artifacts.readArtifact("AllocationStaking")).abi) 11 | saveContractAbi(hre.network.name, 'AvalaunchSale', (await hre.artifacts.readArtifact("AvalaunchSale")).abi) 12 | } 13 | 14 | // We recommend this pattern to be able to use async/await everywhere 15 | // and properly handle errors. 16 | main() 17 | .then(() => process.exit(0)) 18 | .catch(error => { 19 | console.error(error); 20 | process.exit(1); 21 | }); 22 | -------------------------------------------------------------------------------- /scripts/setters/addAdmin.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { getSavedContractAddresses } = require('../utils') 3 | const { ethers, web3 } = hre 4 | 5 | async function main() { 6 | 7 | const contracts = getSavedContractAddresses()[hre.network.name]; 8 | const admin = await hre.ethers.getContractAt('Admin', contracts['Admin']); 9 | await admin.addAdmin('0x094028E04c1FADf12F5a4Fe6C1b9D2062a252a17') 10 | } 11 | 12 | 13 | main() 14 | .then(() => process.exit(0)) 15 | .catch(error => { 16 | console.error(error); 17 | process.exit(1); 18 | }); 19 | -------------------------------------------------------------------------------- /scripts/setters/erc20_approve.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { saveContractAddress, getSavedContractAddresses } = require('../utils') 3 | const { ethers, web3 } = hre 4 | 5 | 6 | async function main() { 7 | 8 | const contracts = getSavedContractAddresses()[hre.network.name]; 9 | 10 | const amount = ethers.utils.parseEther('720000'); 11 | //Arrow markets token 12 | const token = await hre.ethers.getContractAt('XavaToken', '0x5c5e384Bd4e36724B2562cCAA582aFd125277C9B'); 13 | // Avalaunch sale. 14 | const spender = "0xC354D85c24A724FdA55084075fDf25c9e9cf35Aa"; 15 | 16 | const resp = await token.approve( 17 | spender, 18 | amount 19 | ); 20 | 21 | console.log(`Successfully approved ${spender} to spend ${amount}. \n TxHash: ${resp.hash}`); 22 | } 23 | 24 | 25 | main() 26 | .then(() => process.exit(0)) 27 | .catch(error => { 28 | console.error(error); 29 | process.exit(1); 30 | }); 31 | -------------------------------------------------------------------------------- /scripts/setters/setAllocationStakingFee.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { saveContractAddress, getSavedContractAddresses } = require('../utils') 3 | const { ethers, web3 } = hre 4 | 5 | async function getCurrentBlockTimestamp() { 6 | return (await ethers.provider.getBlock('latest')).timestamp; 7 | } 8 | 9 | async function main() { 10 | 11 | const contracts = getSavedContractAddresses()[hre.network.name]; 12 | 13 | const allocationStaking = await hre.ethers.getContractAt('AllocationStaking', contracts['AllocationStaking']); 14 | await allocationStaking.setDepositFee(2, 100); 15 | } 16 | 17 | 18 | main() 19 | .then(() => process.exit(0)) 20 | .catch(error => { 21 | console.error(error); 22 | process.exit(1); 23 | }); 24 | -------------------------------------------------------------------------------- /scripts/setters/setSalesFactory.js: -------------------------------------------------------------------------------- 1 | // scripts/upgrade-box.js 2 | const { ethers, upgrades } = require("hardhat"); 3 | const { getSavedContractAddresses } = require('../utils') 4 | const hre = require("hardhat"); 5 | 6 | async function main() { 7 | const contracts = getSavedContractAddresses()[hre.network.name]; 8 | const allocationStaking = await hre.ethers.getContractAt( 9 | 'AllocationStaking', 10 | contracts['AllocationStakingProxy'] 11 | ); 12 | 13 | let salesFactory = await allocationStaking.salesFactory(); 14 | console.log(salesFactory); 15 | 16 | await allocationStaking.setSalesFactory(contracts['SalesFactory']); 17 | 18 | salesFactory = await allocationStaking.salesFactory(); 19 | console.log(salesFactory); 20 | } 21 | 22 | 23 | main() 24 | .then(() => process.exit(0)) 25 | .catch(error => { 26 | console.error(error); 27 | process.exit(1); 28 | }); 29 | -------------------------------------------------------------------------------- /scripts/setters/setSalesFactoryOnMarketplace.js: -------------------------------------------------------------------------------- 1 | // scripts/upgrade-box.js 2 | const { getSavedContractAddresses } = require('../utils') 3 | const hre = require("hardhat"); 4 | 5 | async function main() { 6 | const contracts = getSavedContractAddresses()[hre.network.name]; 7 | const avalaunchMarketplace = await hre.ethers.getContractAt( 8 | 'AvalaunchMarketplace', 9 | contracts['AvalaunchMarketplaceProxy'] 10 | ); 11 | 12 | let salesFactory = await avalaunchMarketplace.factory(); 13 | console.log(salesFactory); 14 | 15 | await avalaunchMarketplace.setFactory(contracts['SalesFactory']); 16 | 17 | salesFactory = await avalaunchMarketplace.factory(); 18 | console.log(salesFactory); 19 | } 20 | 21 | 22 | main() 23 | .then(() => process.exit(0)) 24 | .catch(error => { 25 | console.error(error); 26 | process.exit(1); 27 | }); -------------------------------------------------------------------------------- /scripts/setters/setWithdrawPenalty.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { getSavedContractAddresses } = require('../utils'); 3 | const config = require('../configs/config.json'); 4 | 5 | async function main() { 6 | const c = config[hre.network.name]; 7 | const allocationStakingProxyAddress = getSavedContractAddresses()[hre.network.name]["AllocationStakingProxy"]; 8 | const allocationStakingProxy = await hre.ethers.getContractAt("AllocationStaking", allocationStakingProxyAddress); 9 | 10 | 11 | 12 | console.log( 13 | c.postSaleWithdrawPenaltyPercent, 14 | c.postSaleWithdrawPenaltyLength, 15 | c.postSaleWithdrawPenaltyPrecision 16 | ) 17 | 18 | await allocationStakingProxy.setPostSaleWithdrawPenaltyPercentAndLength( 19 | c.postSaleWithdrawPenaltyPercent, 20 | c.postSaleWithdrawPenaltyLength, 21 | c.postSaleWithdrawPenaltyPrecision 22 | ); 23 | } 24 | 25 | 26 | main() 27 | .then(() => process.exit(0)) 28 | .catch(error => { 29 | console.error(error); 30 | process.exit(1); 31 | }); 32 | -------------------------------------------------------------------------------- /scripts/setters/set_new_sale_implementation.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { getSavedContractAddresses, saveContractAddress} = require('../utils'); 3 | const { ethers } = hre; 4 | 5 | async function main() { 6 | const contracts = getSavedContractAddresses()[hre.network.name]; 7 | 8 | const saleFactory = await ethers.getContractFactory("AvalaunchSaleV2"); 9 | const saleImplementation = await saleFactory.deploy(); 10 | await saleImplementation.deployed(); 11 | 12 | saveContractAddress(hre.network.name, "Sale-Implementation", saleImplementation.address); 13 | console.log('Sale implementation deployed to: ', saleImplementation.address); 14 | 15 | const salesFactory = await ethers.getContractAt("SalesFactory", contracts['SalesFactory']); 16 | await salesFactory.setImplementation(saleImplementation.address); 17 | console.log('Sale implementation set on SalesFactory!'); 18 | } 19 | 20 | main() 21 | .then(() => process.exit(0)) 22 | .catch(error => { 23 | console.error(error); 24 | process.exit(1); 25 | }); 26 | -------------------------------------------------------------------------------- /scripts/styling.js: -------------------------------------------------------------------------------- 1 | const b = "\x1b[1m"; // Brightness 2 | const u = "\x1b[4m"; // Underline 3 | const g = "\x1b[32m"; // Green 4 | const r = "\x1b[31m"; // Red 5 | const e = "\x1b[0m"; // End style 6 | 7 | const greenOut = (text) => { 8 | return g + text + e; 9 | } 10 | 11 | const redOut = (text) => { 12 | return r + text + e; 13 | } 14 | 15 | const boldOut = (text) => { 16 | return b + text + e; 17 | } 18 | 19 | module.exports = { 20 | b, 21 | u, 22 | g, 23 | r, 24 | e, 25 | greenOut, 26 | redOut, 27 | boldOut 28 | } 29 | -------------------------------------------------------------------------------- /scripts/tenderly/push_tenderly.js: -------------------------------------------------------------------------------- 1 | const hre = require('hardhat'); 2 | const fetch = require('axios'); 3 | const { getSavedContractAddresses } = require('../utils'); 4 | require('dotenv').config(); 5 | 6 | const tenderlyPush = async (contracts) => { 7 | const axios = require('axios') 8 | await axios.post(`https://api.tenderly.co/api/v1/account/${process.env.TENDERLY_USERNAME}/project/${process.env.PROJECT_NAME}/addresses`, { 9 | "contracts" : contracts 10 | }, { 11 | headers: { 12 | 'Content-Type': 'application/json', 13 | 'x-access-key' : process.env.ACCESS_KEY 14 | } 15 | }) 16 | .then(res => { 17 | console.log(`statusCode: ${res.status} ✅`); 18 | }) 19 | .catch(error => { 20 | console.error(error) 21 | }); 22 | } 23 | 24 | 25 | async function main() { 26 | 27 | const contracts = getSavedContractAddresses()[hre.network.name]; 28 | let payload = []; 29 | 30 | Object.keys(contracts).forEach(name => { 31 | payload.push({ 32 | "network_id": hre.network.config.chainId.toString(), 33 | "address": contracts[name], 34 | "display_name": name 35 | }); 36 | }); 37 | 38 | await tenderlyPush(payload); 39 | } 40 | 41 | main() 42 | .then(() => process.exit(0)) 43 | .catch(error => { 44 | console.error(error); 45 | process.exit(1) 46 | }); 47 | -------------------------------------------------------------------------------- /scripts/time.js: -------------------------------------------------------------------------------- 1 | const unixTimestampToReadableDate = (timestamp) => { 2 | return (new Date(timestamp * 1000)).toLocaleString() 3 | } 4 | 5 | module.exports = { 6 | unixTimestampToReadableDate 7 | } -------------------------------------------------------------------------------- /scripts/upgrade/upgradeAllocationStaking.js: -------------------------------------------------------------------------------- 1 | // scripts/upgrade-box.js 2 | const { ethers, upgrades } = require("hardhat"); 3 | const { getSavedContractAddresses, getSavedProxyABI, saveContractAddress} = require('../utils') 4 | const hre = require("hardhat"); 5 | 6 | async function main() { 7 | // const contracts = getSavedContractAddresses()[hre.network.name]; 8 | // const proxyAdminAbi = getSavedProxyABI()['ProxyAdmin']; 9 | 10 | //console.log(proxyAdminAbi); 11 | // const proxyAdmin = await hre.ethers.getContractAt(proxyAdminAbi, contracts['ProxyAdmin']); 12 | // 13 | // const allocationStakingProxy = contracts["AllocationStakingProxy"]; 14 | // console.log("Proxy:", allocationStakingProxy); 15 | 16 | const AllocationStakingImplementation = await ethers.getContractFactory("AllocationStaking"); 17 | const allocationStakingImpl = await AllocationStakingImplementation.deploy(); 18 | await allocationStakingImpl.deployed(); 19 | 20 | console.log("New Implementation:", allocationStakingImpl.address); 21 | 22 | // await proxyAdmin.upgrade(allocationStakingProxy, allocationStakingImpl.address); 23 | // console.log("AllocationStaking contract upgraded"); 24 | } 25 | 26 | 27 | main() 28 | .then(() => process.exit(0)) 29 | .catch(error => { 30 | console.error(error); 31 | process.exit(1); 32 | }); 33 | -------------------------------------------------------------------------------- /scripts/upgrade/upgradeCollateral.js: -------------------------------------------------------------------------------- 1 | // scripts/upgrade-box.js 2 | const { ethers, upgrades } = require("hardhat"); 3 | const { getSavedContractAddresses, getSavedProxyABI, saveContractAddress } = require('../utils') 4 | const hre = require("hardhat"); 5 | 6 | async function main() { 7 | const contracts = getSavedContractAddresses()[hre.network.name]; 8 | const proxyAdminAbi = getSavedProxyABI()['ProxyAdmin']; 9 | 10 | //console.log(proxyAdminAbi); 11 | const proxyAdmin = await hre.ethers.getContractAt(proxyAdminAbi, contracts['ProxyAdmin']); 12 | 13 | const collateralProxy = contracts["AvalaunchCollateralProxy"]; 14 | console.log("Proxy:", collateralProxy); 15 | 16 | const CollateralFactory = await ethers.getContractFactory("AvalaunchCollateral"); 17 | const collateralImplementation = await CollateralFactory.deploy(); 18 | await collateralImplementation.deployed(); 19 | 20 | console.log("New Implementation:", collateralImplementation.address); 21 | saveContractAddress(hre.network.name, "AvalaunchCollateral", collateralImplementation.address); 22 | 23 | await proxyAdmin.upgrade(collateralProxy, collateralImplementation.address); 24 | console.log("Collateral contract upgraded"); 25 | } 26 | 27 | 28 | main() 29 | .then(() => process.exit(0)) 30 | .catch(error => { 31 | console.error(error); 32 | process.exit(1); 33 | }); 34 | -------------------------------------------------------------------------------- /scripts/upgrade/upgradeMarketplace.js: -------------------------------------------------------------------------------- 1 | // scripts/upgrade-box.js 2 | const { ethers } = require("hardhat"); 3 | const { getSavedContractAddresses, saveContractAddress, getSavedProxyABI} = require('../utils') 4 | const hre = require("hardhat"); 5 | 6 | async function main() { 7 | const contracts = getSavedContractAddresses()[hre.network.name]; 8 | const proxyAdminAbi = getSavedProxyABI()['ProxyAdmin']; 9 | 10 | const proxyAdmin = await hre.ethers.getContractAt(proxyAdminAbi, contracts['ProxyAdmin']); 11 | 12 | const marketplaceProxy = contracts["AvalaunchMarketplaceProxy"]; 13 | console.log("Proxy:", marketplaceProxy); 14 | 15 | const MarketplaceFactory = await ethers.getContractFactory("AvalaunchMarketplace"); 16 | const marketplaceImplementation = await MarketplaceFactory.deploy(); 17 | await marketplaceImplementation.deployed(); 18 | 19 | console.log("New Implementation:", marketplaceImplementation.address); 20 | saveContractAddress(hre.network.name, "AvalaunchMarketplace", marketplaceImplementation.address); 21 | 22 | await proxyAdmin.upgrade(marketplaceProxy, marketplaceImplementation.address); 23 | console.log("Marketplace contract upgraded"); 24 | } 25 | 26 | 27 | main() 28 | .then(() => process.exit(0)) 29 | .catch(error => { 30 | console.error(error); 31 | process.exit(1); 32 | }); 33 | -------------------------------------------------------------------------------- /scripts/utils.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const path = require('path') 3 | 4 | function getSavedContractAddresses() { 5 | let json 6 | try { 7 | json = fs.readFileSync(path.join(__dirname, '../deployments/contract-addresses.json')) 8 | } catch (err) { 9 | json = '{}' 10 | } 11 | const addrs = JSON.parse(json) 12 | return addrs 13 | } 14 | function getSavedContractABI() { 15 | let json 16 | try { 17 | json = fs.readFileSync(path.join(__dirname, `../deployments/contract-abis.json`)) 18 | } catch (err) { 19 | json = '{}' 20 | } 21 | return JSON.parse(json) 22 | } 23 | 24 | function getSavedProxyABI() { 25 | let json 26 | try { 27 | json = fs.readFileSync(path.join(__dirname, `../deployments/proxy-abis.json`)) 28 | } catch (err) { 29 | json = '{}' 30 | } 31 | return JSON.parse(json) 32 | } 33 | 34 | function saveContractAbi(network, contract, abi) { 35 | const abis = getSavedContractABI() 36 | abis[network] = abis[network] || {} 37 | abis[network][contract] = abi 38 | fs.writeFileSync(path.join(__dirname, `../deployments/contract-abis.json`), JSON.stringify(abis, null, ' ')) 39 | } 40 | 41 | function saveContractAddress(network, contract, address) { 42 | const addrs = getSavedContractAddresses() 43 | addrs[network] = addrs[network] || {} 44 | addrs[network][contract] = address 45 | fs.writeFileSync(path.join(__dirname, '../deployments/contract-addresses.json'), JSON.stringify(addrs, null, ' ')) 46 | } 47 | 48 | module.exports = { 49 | getSavedContractAddresses, 50 | saveContractAddress, 51 | saveContractAbi, 52 | getSavedContractABI, 53 | getSavedProxyABI 54 | } 55 | -------------------------------------------------------------------------------- /test/admin.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require("hardhat"); 2 | const { expect } = require("chai"); 3 | 4 | describe("Admin", function() { 5 | 6 | let Admin; 7 | let deployer, alice, bob, cedric; 8 | let ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; 9 | 10 | beforeEach(async function() { 11 | const accounts = await ethers.getSigners(); 12 | deployer = accounts[0]; 13 | alice = accounts[1]; 14 | bob = accounts[2]; 15 | cedric = accounts[3]; 16 | 17 | const AdminFactory = await ethers.getContractFactory("Admin"); 18 | Admin = await AdminFactory.deploy([deployer.address, alice.address, bob.address]); 19 | }); 20 | 21 | context("Setup", async function() { 22 | it("Should setup the admin contract correctly", async function() { 23 | // Given 24 | let admins = await Admin.getAllAdmins(); 25 | expect(admins.length).to.eq(3); 26 | 27 | // Then 28 | expect(await Admin.isAdmin(deployer.address)).to.be.true; 29 | expect(await Admin.isAdmin(alice.address)).to.be.true; 30 | expect(await Admin.isAdmin(bob.address)).to.be.true; 31 | expect(await Admin.isAdmin(ZERO_ADDRESS)).to.be.false; 32 | }); 33 | }); 34 | 35 | context("Remove admins", async function() { 36 | it("Should allow removal a middle admin using an admin address", async function() { 37 | // Given 38 | let admins = await Admin.getAllAdmins(); 39 | expect(admins.length).to.eq(3); 40 | 41 | // When 42 | await Admin.removeAdmin(admins[1]); 43 | 44 | // Then 45 | admins = await Admin.getAllAdmins(); 46 | expect(admins.length).to.eq(2); 47 | 48 | expect(await Admin.isAdmin(deployer.address)).to.be.true; 49 | expect(await Admin.isAdmin(alice.address)).to.be.false; 50 | expect(await Admin.isAdmin(bob.address)).to.be.true; 51 | expect(await Admin.isAdmin(ZERO_ADDRESS)).to.be.false; 52 | }); 53 | 54 | it("Should not allow a non-admin to removal an admin", async function() { 55 | // Given 56 | expect(await Admin.isAdmin(deployer.address)).to.be.true; 57 | 58 | await Admin.removeAdmin(deployer.address); 59 | expect(await Admin.isAdmin(deployer.address)).to.be.false; 60 | expect(await Admin.isAdmin(alice.address)).to.be.true; 61 | 62 | // Then 63 | await expect(Admin.removeAdmin(alice.address)).to.be.revertedWith('Only admin can call.'); 64 | expect(await Admin.isAdmin(deployer.address)).to.be.false; 65 | expect(await Admin.isAdmin(alice.address)).to.be.true; 66 | }); 67 | 68 | it("Should not allow removing an admin twice", async function() { 69 | // Given 70 | expect(await Admin.isAdmin(alice.address)).to.be.true; 71 | await Admin.removeAdmin(alice.address); 72 | expect(await Admin.isAdmin(alice.address)).to.be.false; 73 | 74 | // Then 75 | await expect(Admin.removeAdmin(alice.address )).to.be.reverted; 76 | }); 77 | }); 78 | 79 | context("Add admins", async function() { 80 | it("Should allow adding an admin", async function() { 81 | // Given 82 | let admins = await Admin.getAllAdmins(); 83 | expect(admins.length).to.eq(3); 84 | expect(await Admin.isAdmin(cedric.address)).to.be.false; 85 | 86 | // When 87 | await Admin.addAdmin(cedric.address); 88 | 89 | // Then 90 | admins = await Admin.getAllAdmins(); 91 | expect(admins.length).to.eq(4); 92 | expect(await Admin.isAdmin(cedric.address)).to.be.true; 93 | }); 94 | 95 | it("Should not allow a non-admin to add an admin", async function() { 96 | // Given 97 | expect(await Admin.isAdmin(deployer.address)).to.be.true; 98 | 99 | await Admin.removeAdmin(deployer.address); 100 | expect(await Admin.isAdmin(deployer.address)).to.be.false; 101 | expect(await Admin.isAdmin(cedric.address)).to.be.false; 102 | 103 | // Then 104 | await expect(Admin.addAdmin(cedric.address)).to.be.revertedWith('Only admin can call.'); 105 | expect(await Admin.isAdmin(deployer.address)).to.be.false; 106 | expect(await Admin.isAdmin(cedric.address)).to.be.false; 107 | }); 108 | 109 | it("Should not allow adding the zero address as an admin", async function() { 110 | // Given 111 | expect(await Admin.isAdmin(ZERO_ADDRESS)).to.be.false; 112 | 113 | // Then 114 | await expect(Admin.addAdmin(ZERO_ADDRESS)).to.be.revertedWith("[RBAC] : Admin must be != than 0x0 address"); 115 | }); 116 | 117 | it("Should not allow adding an admin twice", async function() { 118 | // Given 119 | expect(await Admin.isAdmin(cedric.address)).to.be.false; 120 | await Admin.addAdmin(cedric.address); 121 | expect(await Admin.isAdmin(cedric.address)).to.be.true; 122 | 123 | // Then 124 | await expect(Admin.addAdmin(cedric.address)).to.be.revertedWith("[RBAC] : Admin already exists."); 125 | }); 126 | }); 127 | }); 128 | -------------------------------------------------------------------------------- /test/airdrop.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require("hardhat"); 2 | const { expect } = require("chai"); 3 | const { signTokenWithdrawal } = require("./helpers/signatures.js"); 4 | 5 | const DEPLOYER_PRIVATE_KEY = "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"; 6 | const BAD_DEPLOYER_PRIVATE_KEY = "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff89"; 7 | 8 | describe("Airdrop", () => { 9 | 10 | let Admin; 11 | let deployer, alice, bob, cedric; 12 | let airdropInstance, airdropTokenInstance; 13 | 14 | const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; 15 | const AIRDROP_TOKEN_TOTAL_SUPPLY = "1000000000000000000000000000"; 16 | const WITHDRAW_AMOUNT = 100; 17 | 18 | beforeEach(async function() { 19 | const accounts = await ethers.getSigners(); 20 | deployer = accounts[0]; 21 | alice = accounts[1]; 22 | bob = accounts[2]; 23 | cedric = accounts[3]; 24 | 25 | const AdminFactory = await ethers.getContractFactory("Admin"); 26 | Admin = await AdminFactory.deploy([deployer.address, alice.address, bob.address]); 27 | await Admin.deployed(); 28 | 29 | const AirdropToken = await ethers.getContractFactory("XavaToken"); 30 | airdropTokenInstance = await AirdropToken.deploy("AirdropToken", "AT", AIRDROP_TOKEN_TOTAL_SUPPLY, 18); 31 | await airdropTokenInstance.deployed(); 32 | 33 | const Airdrop = await ethers.getContractFactory("Airdrop"); 34 | airdropInstance = await Airdrop.deploy(airdropTokenInstance.address, Admin.address); 35 | await airdropInstance.deployed(); 36 | 37 | await airdropTokenInstance.transfer(airdropInstance.address, "10000000000000000"); 38 | }); 39 | 40 | context("Main Functionalities", () => { 41 | describe("WithdrawTokens", () => { 42 | it("Should withdraw tokens with proper signature", async () => { 43 | const sig = signTokenWithdrawal(alice.address, WITHDRAW_AMOUNT, airdropInstance.address, DEPLOYER_PRIVATE_KEY); 44 | expect(await airdropInstance.connect(alice).withdrawTokens(sig, WITHDRAW_AMOUNT)) 45 | .to.emit(airdropInstance, "TokensAirdropped") 46 | .withArgs(alice.address, WITHDRAW_AMOUNT); 47 | }); 48 | 49 | it("Should not withdraw tokens with invalid signature", async () => { 50 | const sig = signTokenWithdrawal(alice.address, WITHDRAW_AMOUNT, airdropInstance.address, BAD_DEPLOYER_PRIVATE_KEY); 51 | await expect(airdropInstance.connect(alice).withdrawTokens(sig, WITHDRAW_AMOUNT)) 52 | .to.be.revertedWith('Not eligible to claim tokens!'); 53 | }); 54 | 55 | it("Should not withdraw tokens second time", async () => { 56 | const sig = signTokenWithdrawal(alice.address, WITHDRAW_AMOUNT, airdropInstance.address, DEPLOYER_PRIVATE_KEY); 57 | expect(await airdropInstance.connect(alice).withdrawTokens(sig, WITHDRAW_AMOUNT)) 58 | .to.emit(airdropInstance, "TokensAirdropped") 59 | .withArgs(alice.address, WITHDRAW_AMOUNT); 60 | await expect(airdropInstance.connect(alice).withdrawTokens(sig, WITHDRAW_AMOUNT)) 61 | .to.be.revertedWith("Already claimed!"); 62 | }); 63 | }); 64 | }); 65 | 66 | }); 67 | -------------------------------------------------------------------------------- /test/airdropAVAX.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require("hardhat"); 2 | const { expect } = require("chai"); 3 | const { signTokenWithdrawal } = require("./helpers/signatures.js"); 4 | 5 | const DEPLOYER_PRIVATE_KEY = "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"; 6 | const BAD_DEPLOYER_PRIVATE_KEY = "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff89"; 7 | 8 | describe("Airdrop", () => { 9 | 10 | let Admin; 11 | let deployer, alice, bob, cedric; 12 | let airdropInstance; 13 | 14 | const WITHDRAW_AMOUNT = 1; 15 | 16 | beforeEach(async function() { 17 | const accounts = await ethers.getSigners(); 18 | deployer = accounts[0]; 19 | alice = accounts[1]; 20 | bob = accounts[2]; 21 | cedric = accounts[3]; 22 | 23 | const AdminFactory = await ethers.getContractFactory("Admin"); 24 | Admin = await AdminFactory.deploy([deployer.address, alice.address, bob.address]); 25 | await Admin.deployed(); 26 | 27 | const Airdrop = await ethers.getContractFactory("AirdropAVAX"); 28 | airdropInstance = await Airdrop.deploy(Admin.address); 29 | await airdropInstance.deployed(); 30 | 31 | const value = "10"; 32 | const tx = await deployer.sendTransaction({ 33 | to: ethers.provider._getAddress(airdropInstance.address), 34 | value: ethers.utils.parseEther(value) 35 | }); 36 | }); 37 | 38 | context("Main Functionalities", () => { 39 | describe("WithdrawTokens", () => { 40 | it("Should withdraw tokens with proper signature", async () => { 41 | const sig = signTokenWithdrawal(alice.address, WITHDRAW_AMOUNT, airdropInstance.address, DEPLOYER_PRIVATE_KEY); 42 | expect(await airdropInstance.connect(alice).withdrawTokens(sig, WITHDRAW_AMOUNT)) 43 | .to.emit(airdropInstance, "SentAVAX") 44 | .withArgs(alice.address, WITHDRAW_AMOUNT); 45 | }); 46 | 47 | it("Should not withdraw tokens with invalid signature", async () => { 48 | const sig = signTokenWithdrawal(alice.address, WITHDRAW_AMOUNT, airdropInstance.address, BAD_DEPLOYER_PRIVATE_KEY); 49 | await expect(airdropInstance.connect(alice).withdrawTokens(sig, WITHDRAW_AMOUNT)) 50 | .to.be.revertedWith('Not eligible to claim AVAX!'); 51 | }); 52 | 53 | it("Should not withdraw tokens second time", async () => { 54 | const sig = signTokenWithdrawal(alice.address, WITHDRAW_AMOUNT, airdropInstance.address, DEPLOYER_PRIVATE_KEY); 55 | expect(await airdropInstance.connect(alice).withdrawTokens(sig, WITHDRAW_AMOUNT)) 56 | .to.emit(airdropInstance, "SentAVAX") 57 | .withArgs(alice.address, WITHDRAW_AMOUNT); 58 | await expect(airdropInstance.connect(alice).withdrawTokens(sig, WITHDRAW_AMOUNT)) 59 | .to.be.revertedWith("Already claimed AVAX!"); 60 | }); 61 | }); 62 | }); 63 | 64 | }); 65 | -------------------------------------------------------------------------------- /test/airdropSale.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require("hardhat"); 2 | const { expect } = require("chai"); 3 | const { signMultipleTokenWithdrawal } = require("./helpers/signatures.js"); 4 | 5 | const DEPLOYER_PRIVATE_KEY = "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"; 6 | const BAD_DEPLOYER_PRIVATE_KEY = "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff89"; 7 | 8 | let Admin; 9 | let deployer, alice, bob, cedric; 10 | let airdropInstance, airdropTokenInstance, airdropTokenInstance2; 11 | let amounts, hashedAmounts; 12 | 13 | const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; 14 | const AIRDROP_TOKEN_TOTAL_SUPPLY = "1000000000000000000000000000"; 15 | const WITHDRAW_AMOUNT = 100; 16 | 17 | const before = async () => { 18 | const accounts = await ethers.getSigners(); 19 | deployer = accounts[0]; 20 | alice = accounts[1]; 21 | bob = accounts[2]; 22 | cedric = accounts[3]; 23 | 24 | const AdminFactory = await ethers.getContractFactory("Admin"); 25 | Admin = await AdminFactory.deploy([deployer.address, alice.address, bob.address]); 26 | await Admin.deployed(); 27 | } 28 | 29 | describe("Airdrop", () => { 30 | 31 | beforeEach(async () => { await before(); }); 32 | 33 | context("Main With AVAX", () => { 34 | beforeEach(async function() { 35 | const AirdropToken = await ethers.getContractFactory("XavaToken"); 36 | airdropTokenInstance = await AirdropToken.deploy("AirdropToken", "AT", AIRDROP_TOKEN_TOTAL_SUPPLY, 18); 37 | await airdropTokenInstance.deployed(); 38 | 39 | airdropTokenInstance2 = await AirdropToken.deploy("AirdropToken2", "AT2", AIRDROP_TOKEN_TOTAL_SUPPLY, 18); 40 | await airdropTokenInstance2.deployed(); 41 | 42 | const Airdrop = await ethers.getContractFactory("AirdropSale"); 43 | airdropInstance = await Airdrop.deploy([airdropTokenInstance.address, airdropTokenInstance2.address], Admin.address, true); 44 | await airdropInstance.deployed(); 45 | 46 | await airdropTokenInstance.transfer(airdropInstance.address, "10000000000000000"); 47 | await airdropTokenInstance2.transfer(airdropInstance.address, "10000000000000000"); 48 | 49 | const value = "10"; 50 | const tx = await deployer.sendTransaction({ 51 | to: ethers.provider._getAddress(airdropInstance.address), 52 | value: ethers.utils.parseEther(value) 53 | }); 54 | 55 | amounts = [WITHDRAW_AMOUNT, WITHDRAW_AMOUNT + 1, WITHDRAW_AMOUNT + 2]; 56 | 57 | hashedAmounts = ethers.utils.keccak256( 58 | ethers.utils.solidityPack(['uint256[]'], [[amounts[0], amounts[1], amounts[2]]]) 59 | ); 60 | }); 61 | 62 | describe("WithdrawTokens", () => { 63 | it("Should withdraw tokens with proper signature", async () => { 64 | const sig = signMultipleTokenWithdrawal(alice.address, hashedAmounts, airdropInstance.address, DEPLOYER_PRIVATE_KEY); 65 | expect(await airdropInstance.connect(alice).withdrawTokens(sig, amounts)) 66 | .to.emit(airdropInstance, "SentAVAX") 67 | .withArgs(alice.address, WITHDRAW_AMOUNT); 68 | }); 69 | 70 | it("Should not withdraw tokens with invalid signature", async () => { 71 | const sig = signMultipleTokenWithdrawal(alice.address, hashedAmounts, airdropInstance.address, BAD_DEPLOYER_PRIVATE_KEY); 72 | await expect(airdropInstance.connect(alice).withdrawTokens(sig, amounts)) 73 | .to.be.revertedWith('Not eligible to claim tokens!'); 74 | }); 75 | 76 | it("Should not withdraw tokens second time", async () => { 77 | const sig = signMultipleTokenWithdrawal(alice.address, hashedAmounts, airdropInstance.address, DEPLOYER_PRIVATE_KEY); 78 | expect(await airdropInstance.connect(alice).withdrawTokens(sig, amounts)) 79 | .to.emit(airdropInstance, "SentAVAX") 80 | .withArgs(alice.address, amounts[0]); 81 | await expect(airdropInstance.connect(alice).withdrawTokens(sig, amounts)) 82 | .to.be.revertedWith("Already claimed!"); 83 | }); 84 | }); 85 | }); 86 | 87 | context("Main Without AVAX", () => { 88 | beforeEach(async function() { 89 | const AirdropToken = await ethers.getContractFactory("XavaToken"); 90 | airdropTokenInstance = await AirdropToken.deploy("AirdropToken", "AT", AIRDROP_TOKEN_TOTAL_SUPPLY, 18); 91 | await airdropTokenInstance.deployed(); 92 | 93 | airdropTokenInstance2 = await AirdropToken.deploy("AirdropToken2", "AT2", AIRDROP_TOKEN_TOTAL_SUPPLY, 18); 94 | await airdropTokenInstance2.deployed(); 95 | 96 | const Airdrop = await ethers.getContractFactory("AirdropSale"); 97 | airdropInstance = await Airdrop.deploy([airdropTokenInstance.address, airdropTokenInstance2.address], Admin.address, false); 98 | await airdropInstance.deployed(); 99 | 100 | await airdropTokenInstance.transfer(airdropInstance.address, "10000000000000000"); 101 | await airdropTokenInstance2.transfer(airdropInstance.address, "10000000000000000"); 102 | 103 | hashedAmounts = ethers.utils.keccak256( 104 | ethers.utils.solidityPack( 105 | ['uint256', 'uint256'], 106 | [WITHDRAW_AMOUNT, WITHDRAW_AMOUNT] 107 | ) 108 | ); 109 | 110 | amounts = [WITHDRAW_AMOUNT, WITHDRAW_AMOUNT + 1]; 111 | 112 | hashedAmounts = ethers.utils.keccak256( 113 | ethers.utils.solidityPack(['uint256[]'], [[amounts[0], amounts[1]]]) 114 | ); 115 | }); 116 | 117 | describe("WithdrawTokens", () => { 118 | it("Should withdraw tokens with proper signature", async () => { 119 | const sig = signMultipleTokenWithdrawal(alice.address, hashedAmounts, airdropInstance.address, DEPLOYER_PRIVATE_KEY); 120 | expect(await airdropInstance.connect(alice).withdrawTokens(sig, amounts)) 121 | .to.emit(airdropInstance, "SentERC20") 122 | .withArgs(alice.address, airdropTokenInstance.address, WITHDRAW_AMOUNT); 123 | }); 124 | 125 | it("Should not withdraw tokens with invalid signature", async () => { 126 | const sig = signMultipleTokenWithdrawal(alice.address, hashedAmounts, airdropInstance.address, BAD_DEPLOYER_PRIVATE_KEY); 127 | await expect(airdropInstance.connect(alice).withdrawTokens(sig, amounts)) 128 | .to.be.revertedWith('Not eligible to claim tokens!'); 129 | }); 130 | 131 | it("Should not withdraw tokens second time", async () => { 132 | const sig = signMultipleTokenWithdrawal(alice.address, hashedAmounts, airdropInstance.address, DEPLOYER_PRIVATE_KEY); 133 | expect(await airdropInstance.connect(alice).withdrawTokens(sig, amounts)) 134 | .to.emit(airdropInstance, "SentERC20") 135 | .withArgs(alice.address, airdropTokenInstance.address, amounts[0]); 136 | await expect(airdropInstance.connect(alice).withdrawTokens(sig, amounts)) 137 | .to.be.revertedWith("Already claimed!"); 138 | }); 139 | }); 140 | }); 141 | 142 | context("Main Only AVAX", () => { 143 | beforeEach(async function() { 144 | const Airdrop = await ethers.getContractFactory("AirdropSale"); 145 | airdropInstance = await Airdrop.deploy([], Admin.address, true); 146 | await airdropInstance.deployed(); 147 | 148 | const value = "10"; 149 | const tx = await deployer.sendTransaction({ 150 | to: ethers.provider._getAddress(airdropInstance.address), 151 | value: ethers.utils.parseEther(value) 152 | }); 153 | 154 | amounts = [WITHDRAW_AMOUNT]; 155 | 156 | hashedAmounts = ethers.utils.keccak256( 157 | ethers.utils.solidityPack(['uint256[]'], [[amounts[0]]]) 158 | ); 159 | }); 160 | 161 | describe("WithdrawTokens", () => { 162 | it("Should withdraw tokens with proper signature", async () => { 163 | const sig = signMultipleTokenWithdrawal(alice.address, hashedAmounts, airdropInstance.address, DEPLOYER_PRIVATE_KEY); 164 | expect(await airdropInstance.connect(alice).withdrawTokens(sig, amounts)) 165 | .to.emit(airdropInstance, "SentAVAX") 166 | .withArgs(alice.address, amounts[0]); 167 | }); 168 | 169 | it("Should not withdraw tokens with invalid signature", async () => { 170 | const sig = signMultipleTokenWithdrawal(alice.address, hashedAmounts, airdropInstance.address, BAD_DEPLOYER_PRIVATE_KEY); 171 | await expect(airdropInstance.connect(alice).withdrawTokens(sig, amounts)) 172 | .to.be.revertedWith('Not eligible to claim tokens!'); 173 | }); 174 | 175 | it("Should not withdraw tokens second time", async () => { 176 | const sig = signMultipleTokenWithdrawal(alice.address, hashedAmounts, airdropInstance.address, DEPLOYER_PRIVATE_KEY); 177 | expect(await airdropInstance.connect(alice).withdrawTokens(sig, amounts)) 178 | .to.emit(airdropInstance, "SentAVAX") 179 | .withArgs(alice.address, amounts[0]); 180 | await expect(airdropInstance.connect(alice).withdrawTokens(sig, amounts)) 181 | .to.be.revertedWith("Already claimed!"); 182 | }); 183 | }); 184 | }); 185 | 186 | }); 187 | -------------------------------------------------------------------------------- /test/badge-factory.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require("hardhat"); 2 | const { expect } = require("chai"); 3 | 4 | describe("Badge Factory", () => { 5 | 6 | let Admin; 7 | let deployer, alice, bob, charlie; 8 | let badgeFactory; 9 | 10 | const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; 11 | const CONTRACT_URI = "https://api.avalaunch.app/badge_nfts/metadata" 12 | const URI = "https://api.avalaunch.app/badge_nfts/metadata?id={id}" 13 | const NEW_URI = "https://api.avalaunch.io/new_badge_nfts/metadata?id={id}" 14 | 15 | const BADGE_IDS = [1, 2, 3]; 16 | const BADGE_MULTIPLIERS = [15, 30, 70]; 17 | const BADGE_TRADEABILITIES = [true, false, true]; 18 | 19 | describe("Main Functions", () => { 20 | 21 | beforeEach(async () => { 22 | const accounts = await ethers.getSigners(); 23 | deployer = accounts[0]; 24 | alice = accounts[1]; 25 | bob = accounts[2]; 26 | charlie = accounts[3]; 27 | 28 | const AdminFactory = await ethers.getContractFactory("Admin"); 29 | Admin = await AdminFactory.deploy([deployer.address, alice.address, bob.address]); 30 | await Admin.deployed(); 31 | 32 | const factory = await ethers.getContractFactory("AvalaunchBadgeFactory"); 33 | badgeFactory = await factory.deploy(); 34 | await badgeFactory.deployed(); 35 | 36 | await badgeFactory.initialize(Admin.address, URI, CONTRACT_URI); 37 | }); 38 | 39 | describe("Pausing", () => { 40 | it("Should pause", async () => { 41 | await badgeFactory.pause(); 42 | expect(await badgeFactory.paused()).to.equal(true); 43 | }); 44 | 45 | it("Should unpause", async () => { 46 | await badgeFactory.pause(); 47 | expect(await badgeFactory.paused()).to.equal(true); 48 | await badgeFactory.unpause(); 49 | expect(await badgeFactory.paused()).to.equal(false); 50 | }); 51 | }); 52 | 53 | describe("Setters", () => { 54 | it("Should set new uri", async () => { 55 | await badgeFactory.setNewUri(NEW_URI); 56 | expect(await badgeFactory.uri(0)).to.equal(NEW_URI); 57 | }); 58 | 59 | it("Should set new contract uri", async () => { 60 | await badgeFactory.setNewContractUri(NEW_URI); 61 | expect(await badgeFactory.getContractURI()).to.equal(NEW_URI); 62 | }); 63 | 64 | it("Should add verified marketplace", async () => { 65 | await badgeFactory.addVerifiedMarketplace(bob.address); 66 | expect(await badgeFactory.isMarketplaceVerified(bob.address)).to.equal(true); 67 | }) 68 | 69 | it("Should remove verified marketplace", async () => { 70 | await badgeFactory.addVerifiedMarketplace(bob.address); 71 | expect(await badgeFactory.isMarketplaceVerified(bob.address)).to.equal(true); 72 | await badgeFactory.removeVerifiedMarketplace(bob.address); 73 | expect(await badgeFactory.isMarketplaceVerified(bob.address)).to.equal(false); 74 | }) 75 | }); 76 | 77 | describe("Badge Actions", () => { 78 | describe("Creation", () => { 79 | it("Should create badges", async () => { 80 | await expect(badgeFactory.createBadges( 81 | BADGE_IDS, 82 | BADGE_MULTIPLIERS, 83 | BADGE_TRADEABILITIES 84 | )).to.emit(badgeFactory, "BadgeCreated"); 85 | 86 | expect(await badgeFactory.getLastCreatedBadgeId()).to.equal(3); 87 | expect(await badgeFactory.getBadgeMultiplier(BADGE_IDS[0])).to.equal(BADGE_MULTIPLIERS[0]); 88 | expect(await badgeFactory.getBadgeMultiplier(BADGE_IDS[1])).to.equal(BADGE_MULTIPLIERS[1]); 89 | expect(await badgeFactory.getBadgeMultiplier(BADGE_IDS[2])).to.equal(BADGE_MULTIPLIERS[2]); 90 | }); 91 | }); 92 | 93 | describe("Minting", () => { 94 | beforeEach(async () => { 95 | await badgeFactory.createBadges( 96 | BADGE_IDS, 97 | BADGE_MULTIPLIERS, 98 | BADGE_TRADEABILITIES 99 | ); 100 | }); 101 | 102 | it("Should mint badges", async () => { 103 | expect(await badgeFactory.getBadgeSupply(BADGE_IDS[0])).to.equal(0); 104 | expect(await badgeFactory.getBadgeSupply(BADGE_IDS[1])).to.equal(0); 105 | expect(await badgeFactory.getBadgeSupply(BADGE_IDS[2])).to.equal(0); 106 | 107 | await badgeFactory.mintBadges( 108 | BADGE_IDS, 109 | [alice.address, bob.address, charlie.address] 110 | ); 111 | 112 | expect(await badgeFactory.getBadgeSupply(BADGE_IDS[0])).to.equal(1); 113 | expect(await badgeFactory.getBadgeSupply(BADGE_IDS[1])).to.equal(1); 114 | expect(await badgeFactory.getBadgeSupply(BADGE_IDS[2])).to.equal(1); 115 | }); 116 | }); 117 | 118 | describe("Transfer", () => { 119 | beforeEach(async () => { 120 | await badgeFactory.createBadges( 121 | BADGE_IDS, 122 | BADGE_MULTIPLIERS, 123 | BADGE_TRADEABILITIES 124 | ); 125 | 126 | await badgeFactory.mintBadges( 127 | BADGE_IDS, 128 | [alice.address, bob.address, charlie.address] 129 | ); 130 | 131 | await badgeFactory.addVerifiedMarketplace(bob.address); 132 | await badgeFactory.addVerifiedMarketplace(alice.address); 133 | }); 134 | 135 | it("Should transfer a tradeable badge", async () => { 136 | expect(await badgeFactory.balanceOf(bob.address, BADGE_IDS[0])).to.equal(0); 137 | expect(await badgeFactory.balanceOf(alice.address, BADGE_IDS[0])).to.equal(1); 138 | await badgeFactory.connect(alice).setApprovalForAll(bob.address, true); 139 | await badgeFactory.connect(bob).safeTransferFrom( 140 | alice.address, 141 | bob.address, 142 | BADGE_IDS[0], 143 | 1, 144 | "0x" 145 | ); 146 | expect(await badgeFactory.balanceOf(bob.address, BADGE_IDS[0])).to.equal(1); 147 | expect(await badgeFactory.balanceOf(alice.address, BADGE_IDS[0])).to.equal(0); 148 | }); 149 | 150 | it("Should not transfer a non-tradeable badge", async () => { 151 | expect(await badgeFactory.balanceOf(bob.address, BADGE_IDS[1])).to.equal(1); 152 | expect(await badgeFactory.balanceOf(alice.address, BADGE_IDS[1])).to.equal(0); 153 | await badgeFactory.connect(bob).setApprovalForAll(alice.address, true); 154 | await expect(badgeFactory.connect(alice).safeTransferFrom( 155 | bob.address, 156 | alice.address, 157 | BADGE_IDS[1], 158 | 1, 159 | "0x" 160 | )).to.be.revertedWith("Badge not tradeable."); 161 | }); 162 | 163 | it("Should not transfer a badge when paused", async () => { 164 | await badgeFactory.pause(); 165 | expect(await badgeFactory.paused()).to.equal(true); 166 | 167 | expect(await badgeFactory.balanceOf(bob.address, BADGE_IDS[0])).to.equal(0); 168 | expect(await badgeFactory.balanceOf(alice.address, BADGE_IDS[0])).to.equal(1); 169 | 170 | await badgeFactory.connect(alice).setApprovalForAll(bob.address, true); 171 | await expect(badgeFactory.connect(bob).safeTransferFrom( 172 | alice.address, 173 | bob.address, 174 | BADGE_IDS[0], 175 | 1, 176 | "0x" 177 | )).to.be.revertedWith("ERC1155Pausable: token transfer while paused"); 178 | }); 179 | }); 180 | }); 181 | }); 182 | }); 183 | -------------------------------------------------------------------------------- /test/collateral.js: -------------------------------------------------------------------------------- 1 | const hre = require("hardhat"); 2 | const { expect } = require("chai"); 3 | 4 | let Admin, collateral; 5 | let deployer, alice, bob, cedric; 6 | let ONE_ADDRESS = "0x0000000000000000000000000000000000000001"; 7 | 8 | const sendAsync = (payload) => 9 | new Promise((resolve, reject) => { 10 | hre.web3.currentProvider.send(payload, (err, res) => { 11 | if (err) { 12 | reject(err); 13 | } else { 14 | resolve(res.result); 15 | } 16 | }); 17 | }); 18 | 19 | const generateSignature = async (message, type, primaryType) => { 20 | const data = { 21 | domain: { 22 | name: 'AvalaunchApp', 23 | version: '1', 24 | chainId: 43114, 25 | verifyingContract: collateral.address.toString(), 26 | }, 27 | message, 28 | ...primaryType, 29 | types: { 30 | EIP712Domain: [ 31 | { name: 'name', type: 'string' }, 32 | { name: 'version', type: 'string' }, 33 | { name: 'chainId', type: 'uint256' }, 34 | { name: 'verifyingContract', type: 'address' }, 35 | ], 36 | ...type, 37 | }, 38 | }; 39 | 40 | const msgParams = JSON.stringify(data); 41 | const from = deployer.address; 42 | const params = [from, msgParams]; 43 | const method = 'eth_signTypedData_v4'; 44 | 45 | return await sendAsync( 46 | { 47 | method, 48 | params, 49 | from 50 | } 51 | ); 52 | } 53 | 54 | describe("Collateral", function() { 55 | 56 | beforeEach(async function() { 57 | const accounts = await ethers.getSigners(); 58 | deployer = accounts[0]; 59 | alice = accounts[1]; 60 | bob = accounts[2]; 61 | cedric = accounts[3]; 62 | 63 | const AdminFactory = await ethers.getContractFactory("Admin"); 64 | Admin = await AdminFactory.deploy([deployer.address, alice.address, bob.address]); 65 | 66 | const collateralFactory = await ethers.getContractFactory("AvalaunchCollateral"); 67 | collateral = await collateralFactory.deploy(); 68 | await collateral.deployed(); 69 | await collateral.initialize(deployer.address, Admin.address, 43114); 70 | }); 71 | 72 | context("Deposit & Withdraw", async function () { 73 | it("Should deposit collateral", async function () { 74 | const value = hre.ethers.utils.parseEther("1"); 75 | await collateral.depositCollateral({value: value}); 76 | expect(await hre.ethers.provider.getBalance(collateral.address)).to.equal(value); 77 | }); 78 | 79 | it("Should withdraw collateral", async function () { 80 | const value = hre.ethers.utils.parseEther("1"); 81 | await collateral.depositCollateral({value: value}); 82 | expect(await hre.ethers.provider.getBalance(collateral.address)).to.equal(value); 83 | await expect(collateral.withdrawCollateral(value)) 84 | .to.emit(collateral, "WithdrawnCollateral"); 85 | }); 86 | 87 | it("Should not withdraw more than deposited", async function () { 88 | const value = hre.ethers.utils.parseEther("1"); 89 | await collateral.depositCollateral({value: value}); 90 | expect(await hre.ethers.provider.getBalance(collateral.address)).to.equal(value); 91 | await expect(collateral.withdrawCollateral(value + 1)) 92 | .to.be.revertedWith("Not enough funds."); 93 | }); 94 | }); 95 | 96 | context("Moderator Only Functions", async function () { 97 | it("Should set new moderator", async function () { 98 | expect(await collateral.moderator()).to.equal(deployer.address); 99 | await collateral.setModerator(alice.address); 100 | expect(await collateral.moderator()).to.equal(alice.address); 101 | }); 102 | 103 | it("Should approve sale", async function () { 104 | expect(await collateral.isSaleApprovedByModerator(ONE_ADDRESS)).to.equal(false); 105 | await collateral.approveSale(ONE_ADDRESS); 106 | expect(await collateral.isSaleApprovedByModerator(ONE_ADDRESS)).to.equal(true); 107 | }); 108 | }); 109 | 110 | context("Miscellaneous", async function () { 111 | it("get TVL", async function () { 112 | expect(await collateral.getTVL()).to.equal(await hre.ethers.provider.getBalance(collateral.address)); 113 | }); 114 | }); 115 | 116 | context("Signature Testing", async function() { 117 | it("Should verify user's autoBuy signature", async function() { 118 | let messageJSON = { 119 | confirmationMessage: "Turn AutoBUY ON.", 120 | saleAddress: ONE_ADDRESS 121 | }; 122 | let message = eval(messageJSON); 123 | 124 | let type = { 125 | AutoBuy: [ 126 | { name: 'confirmationMessage', type: 'string' }, 127 | { name: 'saleAddress', type: 'address' } 128 | ], 129 | }; 130 | 131 | let primaryType = { 132 | primaryType: 'AutoBuy' 133 | }; 134 | 135 | expect(await collateral.verifyAutoBuySignature( 136 | deployer.address, 137 | ONE_ADDRESS, 138 | await generateSignature(message, type, primaryType) 139 | )).to.equal(true); 140 | }); 141 | 142 | it("Should fail verifying user's autoBuy signature - bad user", async function() { 143 | let messageJSON = { 144 | confirmationMessage: "Turn AutoBUY ON.", 145 | saleAddress: ONE_ADDRESS 146 | }; 147 | let message = eval(messageJSON); 148 | 149 | let type = { 150 | AutoBuy: [ 151 | { name: 'confirmationMessage', type: 'string' }, 152 | { name: 'saleAddress', type: 'address' } 153 | ], 154 | }; 155 | 156 | let primaryType = { 157 | primaryType: 'AutoBuy' 158 | }; 159 | 160 | expect(await collateral.verifyAutoBuySignature( 161 | alice.address, 162 | ONE_ADDRESS, 163 | await generateSignature(message, type, primaryType) 164 | )).to.equal(false); 165 | }); 166 | 167 | it("Should verify user's boost signature", async function() { 168 | let messageJSON = { 169 | confirmationMessage: "Boost participation.", 170 | saleAddress: ONE_ADDRESS 171 | }; 172 | let message = eval(messageJSON); 173 | 174 | let type = { 175 | Boost: [ 176 | { name: 'confirmationMessage', type: 'string' }, 177 | { name: 'saleAddress', type: 'address' } 178 | ], 179 | }; 180 | 181 | let primaryType = { 182 | primaryType: 'Boost' 183 | }; 184 | 185 | expect(await collateral.verifyBoostSignature( 186 | deployer.address, 187 | ONE_ADDRESS, 188 | await generateSignature(message, type, primaryType) 189 | )).to.equal(true); 190 | }); 191 | 192 | it("Should fail verifying user's boost signature - bad user", async function() { 193 | let messageJSON = { 194 | confirmationMessage: "Boost participation.", 195 | saleAddress: ONE_ADDRESS 196 | }; 197 | let message = eval(messageJSON); 198 | 199 | let type = { 200 | Boost: [ 201 | { name: 'confirmationMessage', type: 'string' }, 202 | { name: 'saleAddress', type: 'address' } 203 | ], 204 | }; 205 | 206 | let primaryType = { 207 | primaryType: 'Boost' 208 | }; 209 | 210 | expect(await collateral.verifyBoostSignature( 211 | alice.address, 212 | ONE_ADDRESS, 213 | await generateSignature(message, type, primaryType) 214 | )).to.equal(false); 215 | }); 216 | }); 217 | }); 218 | -------------------------------------------------------------------------------- /test/helpers/signatures.js: -------------------------------------------------------------------------------- 1 | const ethUtil = require("ethereumjs-util"); 2 | const {ethers} = require("hardhat"); 3 | 4 | function generateSignature(digest, privateKey) { 5 | // prefix with "\x19Ethereum Signed Message:\n32" 6 | // Reference: https://github.com/OpenZeppelin/openzeppelin-contracts/issues/890 7 | const prefixedHash = ethUtil.hashPersonalMessage(ethUtil.toBuffer(digest)); 8 | 9 | // sign message 10 | const {v, r, s} = ethUtil.ecsign(prefixedHash, Buffer.from(privateKey, 'hex')) 11 | 12 | // generate signature by concatenating r(32), s(32), v(1) in this order 13 | // Reference: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/76fe1548aee183dfcc395364f0745fe153a56141/contracts/ECRecovery.sol#L39-L43 14 | const vb = Buffer.from([v]); 15 | const signature = Buffer.concat([r, s, vb]); 16 | 17 | return signature; 18 | } 19 | 20 | function signTokenWithdrawal(beneficiary, amount, contractAddress, privateKey) { 21 | // compute keccak256(abi.encodePacked(user, roundId, address(this))) 22 | const digest = ethers.utils.keccak256( 23 | ethers.utils.solidityPack( 24 | ['address', 'uint256', 'address'], 25 | [beneficiary, amount, contractAddress] 26 | ) 27 | ); 28 | 29 | return generateSignature(digest, privateKey); 30 | } 31 | 32 | function signMultipleTokenWithdrawal(beneficiary, hashedAmounts, contractAddress, privateKey) { 33 | const coder = new ethers.utils.AbiCoder; 34 | const digest = ethers.utils.keccak256( 35 | coder.encode( 36 | ['address', 'bytes32', 'address'], 37 | [beneficiary, hashedAmounts, contractAddress] 38 | ) 39 | ); 40 | return generateSignature(digest, privateKey); 41 | } 42 | 43 | module.exports = { 44 | signTokenWithdrawal, 45 | signMultipleTokenWithdrawal 46 | } 47 | --------------------------------------------------------------------------------