Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/codecov.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ jobs:
with:
node-version: '${{ matrix.node-version }}'
- name: Install dependencies
run: yarn install
run: |
git config --global url.https://github.com/.insteadOf git://github.com/
yarn install
- name: Run tests
run: npx hardhat coverage --network hardhat --testfiles test
- name: Codecov
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/solhint-lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ jobs:
with:
node-version: '${{ matrix.node-version }}'
- name: Install dependencies
run: yarn install
run: |
git config --global url.https://github.com/.insteadOf git://github.com/
yarn install
- name: Install solhint
run: npm install -g solhint && solhint --init
- name: Lint
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/unit-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ jobs:
with:
node-version: '${{ matrix.node-version }}'
- name: Install dependencies
run: yarn install
run: |
git config --global url.https://github.com/.insteadOf git://github.com/
yarn install
- name: Setup node
run: npx hardhat node &
- name: Run tests
Expand Down
15 changes: 15 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"overrides": [
{
"files": "*.sol",
"options": {
"printWidth": 120,
"tabWidth": 4,
"useTabs": false,
"singleQuote": false,
"bracketSpacing": true,
"explicitTypes": "always"
}
}
]
}
38 changes: 11 additions & 27 deletions contracts/Admin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,27 @@
pragma solidity 0.6.12;

contract Admin {

// Listing all admins
address [] public admins;
address[] public admins;

// Modifier for easier checking if user is admin
mapping(address => bool) public isAdmin;

// Modifier restricting access to only admin
modifier onlyAdmin {
modifier onlyAdmin() {
require(isAdmin[msg.sender], "Only admin can call.");
_;
}

// Constructor to set initial admins during deployment
constructor (address [] memory _admins) public {
for(uint i = 0; i < _admins.length; i++) {
constructor(address[] memory _admins) public {
for (uint256 i = 0; i < _admins.length; i++) {
admins.push(_admins[i]);
isAdmin[_admins[i]] = true;
}
}

function addAdmin(
address _adminAddress
)
external
onlyAdmin
{
function addAdmin(address _adminAddress) external onlyAdmin {
// Can't add 0x address as an admin
require(_adminAddress != address(0x0), "[RBAC] : Admin must be != than 0x0 address");
// Can't add existing admin
Expand All @@ -39,26 +33,21 @@ contract Admin {
isAdmin[_adminAddress] = true;
}

function removeAdmin(
address _adminAddress
)
external
onlyAdmin
{
function removeAdmin(address _adminAddress) external onlyAdmin {
// Admin has to exist
require(isAdmin[_adminAddress]);
require(admins.length > 1, "Can not remove all admins since contract becomes unusable.");
uint i = 0;
uint256 i = 0;

while(admins[i] != _adminAddress) {
if(i == admins.length) {
while (admins[i] != _adminAddress) {
if (i == admins.length) {
revert("Passed admin address does not exist");
}
i++;
}

// Copy the last admin position to the current index
admins[i] = admins[admins.length-1];
admins[i] = admins[admins.length - 1];

isAdmin[_adminAddress] = false;

Expand All @@ -67,12 +56,7 @@ contract Admin {
}

// Fetch all admins
function getAllAdmins()
external
view
returns (address [] memory)
{
function getAllAdmins() external view returns (address[] memory) {
return admins;
}

}
1 change: 1 addition & 0 deletions contracts/AvalaunchCollateral.sol
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.6.12;

import "@openzeppelin/contracts/proxy/Initializable.sol";
Expand Down
29 changes: 29 additions & 0 deletions contracts/interfaces/IAvalaunchSale.sol
Original file line number Diff line number Diff line change
@@ -1,10 +1,39 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.6.12;

/**
* IAvalaunchSale contract.
* Date created: 3.3.22.
*/
interface IAvalaunchSale {
event TokensSold(address user, uint256 amount);
event UserRegistered(address user, uint256 roundId);
event TokenPriceSet(uint256 newPrice);
event MaxParticipationSet(uint256 roundId, uint256 maxParticipation);
event TokensWithdrawn(address user, uint256 amount);
event SaleCreated(
address saleOwner,
uint256 tokenPriceInAVAX,
uint256 amountOfTokensToSell,
uint256 saleEnd,
uint256 tokenPriceInUSD
);
event RegistrationTimeSet(
uint256 registrationTimeStarts,
uint256 registrationTimeEnds
);
event RoundAdded(
uint256 roundId,
uint256 startTime,
uint256 maxParticipation
);
event RegistrationAVAXRefunded(address user, uint256 amountRefunded);
event TokensWithdrawnToDexalot(address user, uint256 amount);
event GateClosed(uint256 time);
event ParticipationMigrated(address user, uint256 vaultId);
event VaultBurned(address user, uint256 vaultId);
event ParticipationBoosted(address user, uint256 amountAVAX, uint256 amountTokens);

function autoParticipate(
address user,
uint256 amount,
Expand Down
1 change: 1 addition & 0 deletions contracts/interfaces/ICollateral.sol
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.6.12;

interface ICollateral {
Expand Down
64 changes: 64 additions & 0 deletions contracts/libraries/DexalotLib.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.6.12;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../interfaces/IERC20Metadata.sol";
import "../interfaces/IDexalotPortfolio.sol";

library DexalotLib {
struct DexalotConfig {
// Pointer to dexalot portfolio smart-contract
IDexalotPortfolio dexalotPortfolio;
// If Dexalot Withdrawals are supported
bool supportsDexalotWithdraw;
// Represent amount of seconds before 0 portion unlock users can at earliest move their tokens to dexalot
uint256 dexalotUnlockTime;
}

/// @notice If sale supports early withdrawals to Dexalot.
function setParams(
DexalotConfig storage dexa,
address _dexalotPortfolio,
uint256 _dexalotUnlockTime
) public {
require(
address(dexa.dexalotPortfolio) == address(0x0),
"Dexalot Portfolio already set."
);
require(
_dexalotPortfolio != address(0x0),
"Cannot set zero address as Dexalot Portfolio."
);
dexa.dexalotPortfolio = IDexalotPortfolio(_dexalotPortfolio);
dexa.dexalotUnlockTime = _dexalotUnlockTime;
dexa.supportsDexalotWithdraw = true;
}

function performChecks(DexalotConfig storage dexa)
public
view
returns (bool)
{
require(
dexa.supportsDexalotWithdraw,
"Dexalot Portfolio withdrawal not supported."
);
require(
block.timestamp >= dexa.dexalotUnlockTime,
"Dexalot Portfolio withdrawal not unlocked."
);
}

function getTokenSymbolBytes32(IERC20 _token)
public
view
returns (bytes32 _symbol)
{
// get token symbol as string memory
string memory symbol = IERC20Metadata(address(_token)).symbol();
// parse token symbol to bytes32 format - to fit dexalot function interface
assembly {
_symbol := mload(add(symbol, 32))
}
}
}
87 changes: 87 additions & 0 deletions contracts/libraries/ParticipationLib.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.6.12;

import "@openzeppelin/contracts/math/SafeMath.sol";
import "../sales/SaleVault.sol";
import "../libraries/VestingLib.sol";

library ParticipationLib {
using SafeMath for uint256;
// Participation structure
struct Participation {
uint256 amountBought;
uint256 amountAVAXPaid;
uint256 timeParticipated;
uint256 roundId;
bool[] isPortionWithdrawn;
bool[] isPortionWithdrawnToDexalot;
bool isParticipationBoosted;
uint256 boostedAmountAVAXPaid;
uint256 boostedAmountBought;
}

// Migrate participation details from user to vault NFT
function migrate(Participation storage p, SaleVault saleVault) public returns (uint256) {
// Check if there are portions left to withdraw
uint256 portionsLeft;

for (uint256 i = 0; i < p.isPortionWithdrawn.length; i++) {
if (!p.isPortionWithdrawn[i]) portionsLeft++;
}

require(portionsLeft > 0, "All portions withdrawn");

uint256 vaultId = saleVault.currentId();
saleVault.mint(msg.sender);
return vaultId;
}

function burn(
Participation storage p,
SaleVault saleVault,
uint256 vaultId
) public returns (uint256) {
// Check if there are portions left to withdraw
uint256 portionsLeft;

for (uint256 i = 0; i < p.isPortionWithdrawn.length; i++) {
if (!p.isPortionWithdrawn[i]) portionsLeft++;
}

require(portionsLeft == 0, "Not all portions withdrawn");

// Burn NFT
saleVault.burn(vaultId);
}

function setPortionWithdrawn(
Participation storage p,
VestingLib.VestingConfig storage vestingConfig,
uint256 portionId
) public returns (uint256) {
require(portionId < vestingConfig.vestingPercentPerPortion.length, "Portion id out of range.");
require(!p.isPortionWithdrawn[portionId], "Portion already withdrawn.");
if (portionId > 0) {
require(vestingConfig.vestingPortionsUnlockTime[portionId] <= block.timestamp, "Portion not unlocked yet.");
}
p.isPortionWithdrawn[portionId] = true;
return
p.amountBought.mul(vestingConfig.vestingPercentPerPortion[portionId]).div(
vestingConfig.portionVestingPrecision
);
}

function boost(
Participation storage p,
uint256 boostedAmountAVAXPaid,
uint256 amountOfTokensBuying
) public {
require(!p.isParticipationBoosted, "User's participation already boosted.");
// Mark participation as boosted
p.isParticipationBoosted = true;
// Add msg.value to boosted avax paid
p.boostedAmountAVAXPaid = boostedAmountAVAXPaid;
// Add amountOfTokensBuying as boostedAmount
p.boostedAmountBought = amountOfTokensBuying;
}
}
Loading