Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add fee manager for erc-to-erc bridge in POSDAO chain #166

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
04ab82f
Add fee manager erc-to-erc
patitonar Mar 26, 2019
4cfb617
Add erc-to-erc fee manager unit tests
patitonar Mar 26, 2019
96d75f2
Add rewardable erc-to-erc executeAffirmation tests
patitonar Mar 29, 2019
0092b10
Fix truffle version
patitonar Mar 29, 2019
bf2222d
Add fee manager on erc-to-erc deploy script
patitonar Mar 29, 2019
88a503b
Use ERC677BridgeTokenRewardable if rewards distributed on erc-to-erc
patitonar Apr 1, 2019
5400cd9
Add erc-to-erc reward management schema
patitonar Apr 1, 2019
4def1fd
Merge branch '119-Epic-rewards-for-bridge-validators' into 160-fee-er…
patitonar Apr 3, 2019
0ae69e6
Fix package-lock.json
patitonar Apr 3, 2019
05d5a2b
Fix merge conflicts
patitonar Apr 3, 2019
2bc4bd7
Merge branch '119-Epic-rewards-for-bridge-validators' into 160-fee-er…
patitonar Apr 16, 2019
16be3f8
Add event on fee distribution
patitonar Apr 16, 2019
cf81b76
Refactor BaseFeeManager
patitonar Apr 16, 2019
95f2362
Fix _initialize on HomeBridgeErcToErc
patitonar Apr 16, 2019
63fbd12
Move ValidatorsFeeManager constants
patitonar Apr 16, 2019
8ab76b9
Add POSDAOHomeBridgeErcToErc
patitonar Apr 17, 2019
851c0b9
Fix erc_to_erc home deploy script
patitonar Apr 17, 2019
1ca930a
Update erc-to-erc rewards schemas
patitonar Apr 18, 2019
d5c7c5a
Fix erc-to-erc reward schema text
patitonar Apr 22, 2019
3592024
Merge branch '119-Epic-rewards-for-bridge-validators' into 160-fee-er…
patitonar Apr 22, 2019
6b25ffb
Update fee events logic on HomeBridgeErcToErc
patitonar Apr 22, 2019
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
10 changes: 10 additions & 0 deletions REWARD_MANAGEMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,13 @@ Fees are calculated and distributed on Home network. Validators will receive nat
### Home to Foreign transfer
Fees are calculated and distributed on Home network. Validators will receive native coins.
![erc-native-hometoforeign](https://user-images.githubusercontent.com/4614574/51607508-96f47480-1ef3-11e9-93a1-0f1111793f2a.png)

## ERC-TO-ERC

### Foreign to Home transfer
Fees are calculated and distributed on Home network. Validators will receive ERC20 tokens.
![ERC-ERC-ForeignToHome (1)](https://user-images.githubusercontent.com/4614574/56502412-98c8d680-64e8-11e9-8eea-5bcd545d74d9.png)

### Home to Foreign transfer
Fees are calculated and distributed on Home network. Validators will receive ERC20 tokens.
![ERC-ERC-HomeToForeign (1)](https://user-images.githubusercontent.com/4614574/56502454-b8f89580-64e8-11e9-84ae-d9a1c229e0c4.png)
1 change: 1 addition & 0 deletions contracts/IBlockReward.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ interface IBlockReward {
function mintedTotally() public view returns (uint256);
function mintedTotallyByBridge(address _bridge) public view returns(uint256);
function bridgesAllowedLength() external view returns(uint256);
function addBridgeTokenFeeReceivers(uint256 _amount) external;
}
39 changes: 39 additions & 0 deletions contracts/test/BlockReward.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ import "../libraries/SafeMath.sol";
contract BlockReward is IBlockReward {
using SafeMath for uint256;

address[] public validatorList;
uint256 public mintedCoins = 0;
uint256 public feeAmount = 0;
mapping(bytes32 => uint256) internal uintStorage;
bytes32 internal constant MINTED_TOTALLY_BY_BRIDGE = "mintedTotallyByBridge";
address public token;

function () external payable {
}
Expand Down Expand Up @@ -40,4 +43,40 @@ contract BlockReward is IBlockReward {
bytes32 hash = keccak256(abi.encode(MINTED_TOTALLY_BY_BRIDGE, _bridge));
uintStorage[hash] = uintStorage[hash].add(_amount);
}

function setValidatorsRewards(address[] _initialValidators) external {
validatorList = _initialValidators;
}

function setToken(address _token) external {
token = _token;
}

function addBridgeTokenFeeReceivers(uint256 _amount) external {
address[] memory receivers = new address[](validatorList.length);
uint256[] memory rewards = new uint256[](validatorList.length);
feeAmount = _amount;
uint256 feePerValidator = _amount.div(validatorList.length);

uint256 randomValidatorIndex;
uint256 diff = _amount.sub(feePerValidator.mul(validatorList.length));
if (diff > 0) {
randomValidatorIndex = random(validatorList.length);
}

for (uint256 i = 0; i < validatorList.length; i++) {
uint256 feeToDistribute = feePerValidator;
if (diff > 0 && randomValidatorIndex == i) {
feeToDistribute = feeToDistribute.add(diff);
}
receivers[i] = validatorList[i];
rewards[i] = feeToDistribute;
}

require(token.call(abi.encodeWithSignature("mintReward(address[],uint256[])", receivers, rewards)));
}

function random(uint256 _count) public view returns(uint256) {
return uint256(blockhash(block.number.sub(1))) % _count;
}
}
49 changes: 2 additions & 47 deletions contracts/upgradeable_contracts/BaseFeeManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ import "./FeeTypes.sol";
contract BaseFeeManager is EternalStorage, FeeTypes {
using SafeMath for uint256;

bytes32 public constant REWARD_FOR_TRANSFERRING_FROM_HOME = keccak256(abi.encodePacked("reward-transferring-from-home"));

bytes32 public constant REWARD_FOR_TRANSFERRING_FROM_FOREIGN = keccak256(abi.encodePacked("reward-transferring-from-foreign"));

event HomeFeeUpdated(uint256 fee);
event ForeignFeeUpdated(uint256 fee);

Expand Down Expand Up @@ -43,54 +39,13 @@ contract BaseFeeManager is EternalStorage, FeeTypes {
return uintStorage[keccak256(abi.encodePacked("foreignFee"))];
}

function distributeFeeFromAffirmation(uint256 _fee) external {
distributeFeeProportionally(_fee, REWARD_FOR_TRANSFERRING_FROM_FOREIGN);
}
function distributeFeeFromAffirmation(uint256 _fee) external;

function distributeFeeFromSignatures(uint256 _fee) external {
distributeFeeProportionally(_fee, REWARD_FOR_TRANSFERRING_FROM_HOME);
}
function distributeFeeFromSignatures(uint256 _fee) external;

function getFeeManagerMode() public pure returns(bytes4);

function random(uint256 _count) public view returns(uint256) {
return uint256(blockhash(block.number.sub(1))) % _count;
}

function distributeFeeProportionally(uint256 _fee, bytes32 _direction) internal {
IRewardableValidators validators = rewardableValidatorContract();
address[] memory validatorList = validators.validatorList();
uint256 feePerValidator = _fee.div(validatorList.length);

uint256 randomValidatorIndex;
uint256 diff = _fee.sub(feePerValidator.mul(validatorList.length));
if (diff > 0) {
randomValidatorIndex = random(validatorList.length);
}

for (uint256 i = 0; i < validatorList.length; i++) {
uint256 feeToDistribute = feePerValidator;
if (diff > 0 && randomValidatorIndex == i) {
feeToDistribute = feeToDistribute.add(diff);
}
address rewardAddress = validators.getValidatorRewardAddress(validatorList[i]);
onFeeDistribution(rewardAddress, feeToDistribute, _direction);
}
}

function onFeeDistribution(address _rewardAddress, uint256 _fee, bytes32 _direction) internal {
if (_direction == REWARD_FOR_TRANSFERRING_FROM_FOREIGN) {
onAffirmationFeeDistribution(_rewardAddress, _fee);
} else {
onSignatureFeeDistribution(_rewardAddress, _fee);
}
}

function onAffirmationFeeDistribution(address _rewardAddress, uint256 _fee) internal;

function onSignatureFeeDistribution(address _rewardAddress, uint256 _fee) internal;

function rewardableValidatorContract() public view returns(IRewardableValidators) {
return IRewardableValidators(addressStorage[keccak256(abi.encodePacked("validatorContract"))]);
}
}
24 changes: 24 additions & 0 deletions contracts/upgradeable_contracts/BlockRewardFeeManager.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
pragma solidity 0.4.24;

import "./BaseFeeManager.sol";
import "../IBlockReward.sol";

contract BlockRewardFeeManager is BaseFeeManager {

function distributeFeeFromAffirmation(uint256 _fee) external {
distributeFeeFromBlockReward(_fee);
}

function distributeFeeFromSignatures(uint256 _fee) external {
distributeFeeFromBlockReward(_fee);
}

function distributeFeeFromBlockReward(uint256 _fee) internal {
IBlockReward blockReward = _blockRewardContract();
blockReward.addBridgeTokenFeeReceivers(_fee);
}

function _blockRewardContract() internal view returns(IBlockReward) {
return IBlockReward(addressStorage[keccak256(abi.encodePacked("blockRewardContract"))]);
}
}
56 changes: 56 additions & 0 deletions contracts/upgradeable_contracts/ValidatorsFeeManager.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
pragma solidity 0.4.24;

import "./BaseFeeManager.sol";
import "../IRewardableValidators.sol";

contract ValidatorsFeeManager is BaseFeeManager {

bytes32 public constant REWARD_FOR_TRANSFERRING_FROM_HOME = keccak256(abi.encodePacked("reward-transferring-from-home"));

bytes32 public constant REWARD_FOR_TRANSFERRING_FROM_FOREIGN = keccak256(abi.encodePacked("reward-transferring-from-foreign"));

function distributeFeeFromAffirmation(uint256 _fee) external {
distributeFeeProportionally(_fee, REWARD_FOR_TRANSFERRING_FROM_FOREIGN);
}

function distributeFeeFromSignatures(uint256 _fee) external {
distributeFeeProportionally(_fee, REWARD_FOR_TRANSFERRING_FROM_HOME);
}

function rewardableValidatorContract() internal view returns(IRewardableValidators) {
return IRewardableValidators(addressStorage[keccak256(abi.encodePacked("validatorContract"))]);
}

function distributeFeeProportionally(uint256 _fee, bytes32 _direction) internal {
IRewardableValidators validators = rewardableValidatorContract();
address[] memory validatorList = validators.validatorList();
uint256 feePerValidator = _fee.div(validatorList.length);

uint256 randomValidatorIndex;
uint256 diff = _fee.sub(feePerValidator.mul(validatorList.length));
if (diff > 0) {
randomValidatorIndex = random(validatorList.length);
}

for (uint256 i = 0; i < validatorList.length; i++) {
uint256 feeToDistribute = feePerValidator;
if (diff > 0 && randomValidatorIndex == i) {
feeToDistribute = feeToDistribute.add(diff);
}
address rewardAddress = validators.getValidatorRewardAddress(validatorList[i]);
onFeeDistribution(rewardAddress, feeToDistribute, _direction);
}
}

function onFeeDistribution(address _rewardAddress, uint256 _fee, bytes32 _direction) internal {
if (_direction == REWARD_FOR_TRANSFERRING_FROM_FOREIGN) {
onAffirmationFeeDistribution(_rewardAddress, _fee);
} else {
onSignatureFeeDistribution(_rewardAddress, _fee);
}
}

function onAffirmationFeeDistribution(address _rewardAddress, uint256 _fee) internal;

function onSignatureFeeDistribution(address _rewardAddress, uint256 _fee) internal;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
pragma solidity 0.4.24;

import "../BlockRewardFeeManager.sol";

contract FeeManagerErcToErcPOSDAO is BlockRewardFeeManager {

function getFeeManagerMode() public pure returns(bytes4) {
return bytes4(keccak256(abi.encodePacked("manages-both-directions")));
}

function blockRewardContract() public view returns(address) {
return _blockRewardContract();
}

function setBlockRewardContract(address _blockReward) external {
require(_blockReward != address(0) && isContract(_blockReward) && (IBlockReward(_blockReward).bridgesAllowedLength() != 0));
addressStorage[keccak256(abi.encodePacked("blockRewardContract"))] = _blockReward;
}

function isContract(address _addr) internal view returns (bool)
{
uint length;
assembly { length := extcodesize(_addr) }
return length > 0;
}
}
Loading