Skip to content

Commit

Permalink
AddressProvider + AccessController and test deployment ok
Browse files Browse the repository at this point in the history
  • Loading branch information
drikssy committed Sep 19, 2024
1 parent 7a92e1a commit 2af7d14
Show file tree
Hide file tree
Showing 50 changed files with 1,508 additions and 1,322 deletions.
50 changes: 23 additions & 27 deletions contracts/Airdrop.sol
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol";
import {IAirdrop} from "contracts/interfaces/IAirdrop.sol";

contract Airdrop is IAirdrop, Ownable, ReentrancyGuard, Pausable {
// Type declarations
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import { Pausable } from "@openzeppelin/contracts/security/Pausable.sol";
import { IAirdrop } from "contracts/interfaces/IAirdrop.sol";
import { IAddressProvider } from "contracts/interfaces/IAddressProvider.sol";
import { Roles } from "contracts/libraries/Roles.sol";
import { Errors } from "contracts/libraries/Errors.sol";
import { AddressProviderResolver } from "contracts/core/AddressProviderResolver.sol";

contract Airdrop is IAirdrop, AddressProviderResolver, ReentrancyGuard, Pausable {
// Type declarations

// Events

Expand All @@ -18,7 +21,6 @@ contract Airdrop is IAirdrop, Ownable, ReentrancyGuard, Pausable {
bool private started;
bool private daoAllowed;

IERC20 public traitToken;
uint256 public totalTokenAmount;
uint256 public totalValue;

Expand All @@ -34,41 +36,36 @@ contract Airdrop is IAirdrop, Ownable, ReentrancyGuard, Pausable {

// Functions

// constructor(address _traitToken) {
// _setTraitToken(_traitToken);
// }
constructor(address addressProvider) AddressProviderResolver(addressProvider) { }

/**
* external & public functions *******************************
*/

//////////////////////////// write functions ////////////////////////////
function setTraitToken(address _traitToken) external onlyOwner {
_setTraitToken(_traitToken);
}

function startAirdrop(uint256 amount) external whenNotPaused nonReentrant onlyOwner {
function startAirdrop(uint256 amount) external whenNotPaused nonReentrant onlyAirdropAccessor {
if (started) revert Airdrop__AlreadyStarted();
if (amount == 0) revert Airdrop__InvalidAmount();
if (address(traitToken) == address(0)) revert Airdrop__AddressZero();
if (address(_getTraitToken()) == address(0)) revert Airdrop__AddressZero();
started = true;
totalTokenAmount = amount;
traitToken.transferFrom(msg.sender, address(this), amount);
_getTraitToken().transferFrom(msg.sender, address(this), amount);
}

function allowDaoFund() external onlyOwner {
function allowDaoFund() external onlyAirdropAccessor {
if (!started) revert Airdrop__NotStarted();
if (daoAllowed) revert Airdrop__AlreadyAllowed();
daoAllowed = true;
}

function addUserAmount(address user, uint256 amount) external whenNotPaused nonReentrant onlyOwner {
function addUserAmount(address user, uint256 amount) external whenNotPaused nonReentrant onlyAirdropAccessor {
if (!started) revert Airdrop__NotStarted();
userInfo[user] += amount;
totalValue += amount;
}

function subUserAmount(address user, uint256 amount) external whenNotPaused nonReentrant onlyOwner {
function subUserAmount(address user, uint256 amount) external whenNotPaused nonReentrant onlyAirdropAccessor {
if (!started) revert Airdrop__NotStarted();
if (userInfo[user] < amount) revert Airdrop__InvalidAmount();
userInfo[user] -= amount;
Expand All @@ -80,15 +77,15 @@ contract Airdrop is IAirdrop, Ownable, ReentrancyGuard, Pausable {
if (userInfo[msg.sender] <= 0) revert Airdrop__NotEligible();

uint256 amount = (totalTokenAmount * userInfo[msg.sender]) / totalValue;
traitToken.transfer(msg.sender, amount);
_getTraitToken().transfer(msg.sender, amount);
userInfo[msg.sender] = 0;
}

function pause() public onlyOwner {
function pause() public onlyProtocolMaintainer {
_pause();
}

function unpause() public onlyOwner {
function unpause() public onlyProtocolMaintainer {
_unpause();
}

Expand All @@ -104,8 +101,7 @@ contract Airdrop is IAirdrop, Ownable, ReentrancyGuard, Pausable {
/**
* internal & private *******************************************
*/
function _setTraitToken(address _traitToken) private {
if (_traitToken == address(0)) revert Airdrop__AddressZero();
traitToken = IERC20(_traitToken);
function _getTraitToken() private view returns (IERC20) {
return IERC20(_addressProvider.getTrait());
}
}
63 changes: 32 additions & 31 deletions contracts/DAOFund.sol
Original file line number Diff line number Diff line change
@@ -1,42 +1,43 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import { ITrait } from './interfaces/ITrait.sol';
import { IUniswapV2Router01, IUniswapV2Router02 } from './interfaces/IUniswapV2Router.sol';
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { ITrait } from "./interfaces/ITrait.sol";
import { IUniswapV2Router01, IUniswapV2Router02 } from "./interfaces/IUniswapV2Router.sol";
import { AddressProviderResolver } from "contracts/core/AddressProviderResolver.sol";

contract DAOFund {
// Type declarations
contract DAOFund is AddressProviderResolver {
// Imports
// Type declarations

// Events

// Modifiers

// State variables
ITrait public token;
IUniswapV2Router01 public uniswapV2Router;

constructor(address _token, address _router) {
token = ITrait(_token);
uniswapV2Router = IUniswapV2Router02(_router);
}

receive() external payable {
require(msg.value > 0, 'No ETH sent');

address[] memory path = new address[](2);
path[0] = uniswapV2Router.WETH();
path[1] = address(token);

uniswapV2Router.swapExactETHForTokens{ value: msg.value }(
0,
path,
address(this),
block.timestamp
);

require(
token.burn(token.balanceOf(address(this))) == true,
'Token burn failed'
);
}
IUniswapV2Router01 public uniswapV2Router;

constructor(address _router, address _addressProvider) AddressProviderResolver(_addressProvider) {
uniswapV2Router = IUniswapV2Router02(_router);
}

receive() external payable {
require(msg.value > 0, "No ETH sent");

ITrait traitToken = _getTraitToken();
address[] memory path = new address[](2);
path[0] = uniswapV2Router.WETH();
path[1] = address(traitToken);

uniswapV2Router.swapExactETHForTokens{ value: msg.value }(0, path, address(this), block.timestamp);

require(traitToken.burn(traitToken.balanceOf(address(this))) == true, "Token burn failed");
}

/**
* internal & private *******************************************
*/
function _getTraitToken() private view returns (ITrait) {
return ITrait(_addressProvider.getTrait());
}
}
191 changes: 96 additions & 95 deletions contracts/DevFund.sol
Original file line number Diff line number Diff line change
@@ -1,107 +1,108 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol';
import {ReentrancyGuard} from '@openzeppelin/contracts/security/ReentrancyGuard.sol';
import {Pausable} from '@openzeppelin/contracts/security/Pausable.sol';
import {IDevFund} from './interfaces/IDevFund.sol';

contract DevFund is IDevFund, Ownable, ReentrancyGuard, Pausable {
// State variables
uint256 public totalDevWeight;
uint256 public totalRewardDebt;
mapping(address => DevInfo) public devInfo;

// Errors
error DevFund__InvalidWeight();
error DevFund__AlreadyRegistered();
error DevFund__NotRegistered();

receive() external payable {
if (totalDevWeight > 0) {
uint256 amountPerWeight = msg.value / totalDevWeight;
uint256 remaining = msg.value - (amountPerWeight * totalDevWeight);
totalRewardDebt += amountPerWeight;
if (remaining > 0) {
(bool success, ) = payable(owner()).call{ value: remaining }('');
require(success, 'Failed to send Ether to owner');
}
} else {
(bool success, ) = payable(owner()).call{ value: msg.value }('');
require(success, 'Failed to send Ether to owner');
import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import { Pausable } from "@openzeppelin/contracts/security/Pausable.sol";
import { IDevFund } from "./interfaces/IDevFund.sol";
import { AddressProviderResolver } from "contracts/core/AddressProviderResolver.sol";

contract DevFund is IDevFund, AddressProviderResolver, ReentrancyGuard, Pausable {
// State variables
uint256 public totalDevWeight;
uint256 public totalRewardDebt;
mapping(address => DevInfo) public devInfo;
address public ethCollector;

// Errors
error DevFund__InvalidWeight();
error DevFund__AlreadyRegistered();
error DevFund__NotRegistered();
error DevFund__AddressZero();

constructor(address addressProvider, address _ethCollector) AddressProviderResolver(addressProvider) {
if (_ethCollector == address(0)) revert DevFund__AddressZero();
ethCollector = _ethCollector;
}

receive() external payable {
if (totalDevWeight > 0) {
uint256 amountPerWeight = msg.value / totalDevWeight;
uint256 remaining = msg.value - (amountPerWeight * totalDevWeight);
totalRewardDebt += amountPerWeight;
if (remaining > 0) {
(bool success,) = payable(ethCollector).call{ value: remaining }("");
require(success, "Failed to send Ether to owner");
}
} else {
(bool success,) = payable(ethCollector).call{ value: msg.value }("");
require(success, "Failed to send Ether to owner");
}
emit FundReceived(msg.sender, msg.value);
}

function pause() public onlyProtocolMaintainer {
_pause();
}

function unpause() public onlyProtocolMaintainer {
_unpause();
}
emit FundReceived(msg.sender, msg.value);
}

function pause() public onlyOwner {
_pause();
function addDev(address user, uint256 weight) external onlyDevFundAccessor {
DevInfo storage info = devInfo[user];
if (weight == 0) revert DevFund__InvalidWeight();
if (info.weight != 0) revert DevFund__AlreadyRegistered();
info.rewardDebt = totalRewardDebt;
info.weight = weight;
totalDevWeight += weight;
emit AddDev(user, weight);
}

function unpause() public onlyOwner {
_unpause();
function updateDev(address user, uint256 weight) external onlyDevFundAccessor {
DevInfo storage info = devInfo[user];
if (weight == 0) revert DevFund__InvalidWeight();
if (info.weight == 0) revert DevFund__NotRegistered();
totalDevWeight = totalDevWeight - info.weight + weight;
info.pendingRewards += (totalRewardDebt - info.rewardDebt) * info.weight;
info.rewardDebt = totalRewardDebt;
info.weight = weight;
emit UpdateDev(user, weight);
}

function addDev(address user, uint256 weight) external onlyOwner {
DevInfo storage info = devInfo[user];
if(weight == 0) revert DevFund__InvalidWeight();
if(info.weight != 0) revert DevFund__AlreadyRegistered();
info.rewardDebt = totalRewardDebt;
info.weight = weight;
totalDevWeight += weight;
emit AddDev(user, weight);
}

function updateDev(address user, uint256 weight) external onlyOwner {
DevInfo storage info = devInfo[user];
if(weight == 0) revert DevFund__InvalidWeight();
if(info.weight == 0) revert DevFund__NotRegistered();
totalDevWeight = totalDevWeight - info.weight + weight;
info.pendingRewards += (totalRewardDebt - info.rewardDebt) * info.weight;
info.rewardDebt = totalRewardDebt;
info.weight = weight;
emit UpdateDev(user, weight);
}

function removeDev(address user) external onlyOwner {
DevInfo storage info = devInfo[user];
if(info.weight == 0) revert DevFund__NotRegistered();
totalDevWeight -= info.weight;
info.pendingRewards += (totalRewardDebt - info.rewardDebt) * info.weight;
info.rewardDebt = totalRewardDebt;
info.weight = 0;
emit RemoveDev(user);
}

function claim() external whenNotPaused nonReentrant {
DevInfo storage info = devInfo[msg.sender];

uint256 pending = info.pendingRewards +
(totalRewardDebt - info.rewardDebt) *
info.weight;

if (pending > 0) {
uint256 claimedAmount = safeRewardTransfer(msg.sender, pending);
info.pendingRewards = pending - claimedAmount;
emit Claim(msg.sender, claimedAmount);
function removeDev(address user) external onlyDevFundAccessor {
DevInfo storage info = devInfo[user];
if (info.weight == 0) revert DevFund__NotRegistered();
totalDevWeight -= info.weight;
info.pendingRewards += (totalRewardDebt - info.rewardDebt) * info.weight;
info.rewardDebt = totalRewardDebt;
info.weight = 0;
emit RemoveDev(user);
}

info.rewardDebt = totalRewardDebt;
}

function pendingRewards(address user) external view returns (uint256) {
DevInfo storage info = devInfo[user];
return
info.pendingRewards + (totalRewardDebt - info.rewardDebt) * info.weight;
}

function safeRewardTransfer(
address to,
uint256 amount
) internal returns (uint256) {
uint256 _rewardBalance = payable(address(this)).balance;
if (amount > _rewardBalance) amount = _rewardBalance;
(bool success, ) = payable(to).call{ value: amount }('');
require(success, 'Failed to send Reward');
return amount;
}
function claim() external whenNotPaused nonReentrant {
DevInfo storage info = devInfo[msg.sender];

uint256 pending = info.pendingRewards + (totalRewardDebt - info.rewardDebt) * info.weight;

if (pending > 0) {
uint256 claimedAmount = safeRewardTransfer(msg.sender, pending);
info.pendingRewards = pending - claimedAmount;
emit Claim(msg.sender, claimedAmount);
}

info.rewardDebt = totalRewardDebt;
}

function pendingRewards(address user) external view returns (uint256) {
DevInfo storage info = devInfo[user];
return info.pendingRewards + (totalRewardDebt - info.rewardDebt) * info.weight;
}

function safeRewardTransfer(address to, uint256 amount) internal returns (uint256) {
uint256 _rewardBalance = payable(address(this)).balance;
if (amount > _rewardBalance) amount = _rewardBalance;
(bool success,) = payable(to).call{ value: amount }("");
require(success, "Failed to send Reward");
return amount;
}
}
Loading

0 comments on commit 2af7d14

Please sign in to comment.