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
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ Public facing interfaces for kyber network (folder: contracts/sol6):
2. `npm ci`

## Compilation with Buidler
1. `./cmp.sh` to compile contracts for all solidity verseions.
1. `./cmp.sh` to compile contracts for all solidity versions.
2. `./cmpSol6.sh` to compile only sol6 contracts

## Testing with Buidler
1. If contracts have not been compiled, run `./compilation.sh`. This step can be skipped subsequently.
1. If contracts have not been compiled, run `./cmp.sh`. This step can be skipped subsequently.
2. Run `./tst.sh`
3. Use `-f` for running a specific test file.
5. Use `-a` to run tests for all solidity versions. Runs only sol6 tests by default.
Expand All @@ -37,4 +37,4 @@ Public facing interfaces for kyber network (folder: contracts/sol6):
2. Use `-f` for running a specific test file.

### Example Commands
`./coverage.sh -f ./test/sol6/kyberNetwork.js` (Coverage for only kyberNetwork.js)
`./coverage.sh -f ./test/sol6/kyberNetwork.js` (Coverage for only kyberNetwork.js)
5 changes: 4 additions & 1 deletion contracts/sol6/Dao/KyberFeeHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ contract KyberFeeHandler is IKyberFeeHandler, Utils5, DaoOperator, ReentrancyGua
ISanityRate[] internal sanityRateContract;

event FeeDistributed(
IERC20 indexed token,
address indexed platformWallet,
uint256 platformFeeWei,
uint256 rewardWei,
Expand Down Expand Up @@ -186,6 +187,7 @@ contract KyberFeeHandler is IKyberFeeHandler, Utils5, DaoOperator, ReentrancyGua
// only platform fee paid
totalPayoutBalance = totalPayoutBalance.add(platformFee);
emit FeeDistributed(
ETH_TOKEN_ADDRESS,
platformWallet,
platformFee,
0,
Expand All @@ -212,6 +214,7 @@ contract KyberFeeHandler is IKyberFeeHandler, Utils5, DaoOperator, ReentrancyGua

brrAmounts.burnWei = networkFee.sub(brrAmounts.rewardWei).sub(brrAmounts.rebateWei);
emit FeeDistributed(
ETH_TOKEN_ADDRESS,
platformWallet,
platformFee,
brrAmounts.rewardWei,
Expand Down Expand Up @@ -265,7 +268,7 @@ contract KyberFeeHandler is IKyberFeeHandler, Utils5, DaoOperator, ReentrancyGua
emit RewardPaid(staker, epoch, ETH_TOKEN_ADDRESS, amountWei);
}

/// @dev claim reabate per reserve wallet. called by any address
/// @dev claim rebate per reserve wallet. called by any address
/// @param rebateWallet the wallet to claim rebates for. Total accumulated rebate sent to this wallet.
/// @return amountWei amount of rebate claimed
function claimReserveRebate(address rebateWallet)
Expand Down
238 changes: 238 additions & 0 deletions contracts/sol6/Dao/emergency/EmergencyFeeHandler.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
pragma solidity 0.6.6;

import "../../IKyberFeeHandler.sol";
import "../../utils/PermissionGroupsNoModifiers.sol";
import "../../utils/zeppelin/ReentrancyGuard.sol";
import "../../utils/zeppelin/SafeMath.sol";
import "../../utils/Utils5.sol";

/**
* @title kyberFeeHandler
*
* @dev EmergencyFeeHandler works when dao has problem
* rebateBps and rewardBps is only set when initialization
* user can claim platformfee, rebate and reward will be distributed by admin
*/
contract EmergencyKyberFeeHandler is IKyberFeeHandler, PermissionGroupsNoModifiers, ReentrancyGuard, Utils5 {
using SafeMath for uint256;

uint16 public immutable rewardBps;
uint16 public immutable rebateBps;
address public kyberNetwork;

mapping(address => uint256) public feePerPlatformWallet;
uint256 public totalPlatformFeeWei; // total balance in the contract that is for platform fee
mapping(address => uint256) public rebatePerWallet;
uint256 public totalRewardWei;

event HandleFeeFailed(address[] rebateWallets, uint256[] rebateBpsPerWallet, uint256 feeBRRWei);

event HandleFee(
IERC20 indexed token,
address indexed platformWallet,
uint256 platformFeeWei,
address[] rebateWallets,
uint256[] rebateBpsPerWallet,
uint256 feeBRRWei
);

event FeeDistribution(
IERC20 indexed token,
address indexed platformWallet,
uint256 platformFeeWei,
uint256 rewardWei,
uint256 rebateWei,
address[] rebateWallets,
uint256[] rebatePercentBpsPerWallet,
uint256 burnAmountWei
);

event EtherWithdraw(uint256 amount, address sendTo);

event KyberNetworkUpdated(address kyberNetwork);

constructor(
address admin,
address _kyberNetwork,
uint256 _rewardBps,
uint256 _rebateBps,
uint256 _burnBps
) public PermissionGroupsNoModifiers(admin) {
require(_burnBps.add(_rewardBps).add(_rebateBps) == BPS, "Bad BRR values");
rewardBps = uint16(_rewardBps);
rebateBps = uint16(_rebateBps);
kyberNetwork = _kyberNetwork;
}

modifier onlyKyberNetwork {
require(msg.sender == address(kyberNetwork), "only kyberNetwork");
_;
}

/// @dev handleFees function is called per trade on KyberNetwork. unless the trade is not involving any fees.
/// @param token Token currency of fees
/// @param rebateWallets a list of rebate wallets that will get rebate for this trade.
/// @param rebateBpsPerWallet percentage of rebate for each wallet, out of total rebate.
/// @param platformWallet Wallet address that will receive the platfrom fee.
/// @param platformFee Fee amount in wei the platfrom wallet is entitled to.
/// @param networkFee Fee amount (in wei) to be allocated for BRR
function handleFees(
IERC20 token,
address[] calldata rebateWallets,
uint256[] calldata rebateBpsPerWallet,
address platformWallet,
uint256 platformFee,
uint256 networkFee
) external payable override onlyKyberNetwork nonReentrant {
require(token == ETH_TOKEN_ADDRESS, "token not eth");
require(msg.value == platformFee.add(networkFee), "msg.value not equal to total fees");

// handle platform fee
feePerPlatformWallet[platformWallet] = feePerPlatformWallet[platformWallet].add(
platformFee
);
totalPlatformFeeWei = totalPlatformFeeWei.add(platformFee);
emit HandleFee(ETH_TOKEN_ADDRESS, platformWallet, platformFee, rebateWallets, rebateBpsPerWallet, networkFee);

if (networkFee == 0) {
emit FeeDistribution(
ETH_TOKEN_ADDRESS,
platformWallet,
platformFee,
0,
0,
rebateWallets,
rebateBpsPerWallet,
0
);
return;
}

(bool success, ) = address(this).call(
abi.encodeWithSignature(
"calculateAndRecordFeeData(address,uint256,address[],uint256[],uint256)",
platformWallet,
platformFee,
rebateWallets,
rebateBpsPerWallet,
networkFee
)
);
if (!success) {
emit HandleFeeFailed(rebateWallets, rebateBpsPerWallet, networkFee);
}
}

function calculateAndRecordFeeData(
address platformWallet,
uint256 platformFee,
address[] calldata rebateWallets,
uint256[] calldata rebateBpsPerWallet,
uint256 feeBRRWei
) external virtual {
require(msg.sender == address(this), "only Feehandler contract can call this function");
uint256 rebateWei = feeBRRWei.mul(rebateBps).div(BPS);
uint256 rewardWei = feeBRRWei.mul(rewardBps).div(BPS);

rebateWei = updateRebateValues(rebateWei, rebateWallets, rebateBpsPerWallet);

totalRewardWei = totalRewardWei.add(rewardWei);

uint burnAmountWei = feeBRRWei.sub(rewardWei).sub(rebateWei);

emit FeeDistribution(
ETH_TOKEN_ADDRESS,
platformWallet,
platformFee,
rewardWei,
rebateWei,
rebateWallets,
rebateBpsPerWallet,
burnAmountWei
);
}

/// @dev claim accumulated fee per platform wallet. Called by any address
/// @param platformWallet the wallet to claim fee for. Total accumulated fee sent to this wallet.
/// @return amountWei amount of fee claimed
function claimPlatformFee(address platformWallet)
external
override
nonReentrant
returns (uint256 amountWei)
{
require(feePerPlatformWallet[platformWallet] > 1, "no fee to claim");
// Get total amount of fees accumulated
amountWei = feePerPlatformWallet[platformWallet].sub(1);

// redundant check, but can't happen
assert(totalPlatformFeeWei >= amountWei);
totalPlatformFeeWei = totalPlatformFeeWei.sub(amountWei);

feePerPlatformWallet[platformWallet] = 1; // avoid zero to non zero storage cost

(bool success, ) = platformWallet.call{value: amountWei}("");
require(success, "platform fee transfer failed");

emit PlatformFeePaid(platformWallet, ETH_TOKEN_ADDRESS, amountWei);
return amountWei;
}

function withdraw(address payable sendTo, uint256 amount) external nonReentrant {
onlyAdmin();

uint256 balance = address(this).balance;
// check if the remain balance is enough for withdraw and paying platform fee
require(amount <= balance.sub(totalPlatformFeeWei), "amount > available funds");

(bool success, ) = sendTo.call{value: amount}("");
require(success, "withdraw transfer failed");
emit EtherWithdraw(amount, sendTo);
}

/// @dev claimReserveRebate is implemented for IKyberFeeHandler
function claimReserveRebate(address) external override returns (uint256) {
revert("not implemented");
}

/// @dev claimStakerReward is implemented for IKyberFeeHandler
function claimStakerReward(address, uint256) external override returns (uint256) {
revert("not implemented");
}

/// @dev set new kyberNetwork address by daoOperator
/// @param _kyberNetwork new kyberNetwork contract
function setNetworkContract(address _kyberNetwork) external {
onlyAdmin();
require(_kyberNetwork != address(0), "kyberNetwork 0");
if (_kyberNetwork != kyberNetwork) {
kyberNetwork = _kyberNetwork;
emit KyberNetworkUpdated(kyberNetwork);
}
}

function updateRebateValues(
uint256 rebateWei,
address[] memory rebateWallets,
uint256[] memory rebateBpsPerWallet
) internal returns (uint256 totalRebatePaidWei) {
uint256 totalRebateBps;
uint256 walletRebateWei;

for (uint256 i = 0; i < rebateWallets.length; i++) {
require(rebateWallets[i] != address(0), "rebate wallet address 0");

walletRebateWei = rebateWei.mul(rebateBpsPerWallet[i]).div(BPS);
rebatePerWallet[rebateWallets[i]] = rebatePerWallet[rebateWallets[i]].add(
walletRebateWei
);

// a few wei could be left out due to rounding down. so count only paid wei
totalRebatePaidWei = totalRebatePaidWei.add(walletRebateWei);
totalRebateBps = totalRebateBps.add(rebateBpsPerWallet[i]);
}

require(totalRebateBps <= BPS, "rebates more then 100%");
}

}
23 changes: 23 additions & 0 deletions contracts/sol6/Dao/mock/MockEmergencyFeeHandler.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
pragma solidity 0.6.6;

import "../emergency/EmergencyFeeHandler.sol";

contract MockEmergencyFeeHandler is EmergencyKyberFeeHandler {
constructor(
address admin,
address _kyberNetwork,
uint256 _rewardBps,
uint256 _rebateBps,
uint256 _burnBps
) public EmergencyKyberFeeHandler(admin, _kyberNetwork, _rewardBps, _rebateBps, _burnBps) {}

function calculateAndRecordFeeData(
address,
uint256,
address[] calldata,
uint256[] calldata,
uint256
) external override {
revert();
}
}
Loading