Update fee contract implementation
This commit is contained in:
parent
ceb8478528
commit
5991ef31eb
|
@ -3,11 +3,12 @@ pragma solidity 0.4.24;
|
|||
import "../upgradeability/EternalStorage.sol";
|
||||
import "../IFeeManager.sol";
|
||||
import "../libraries/SafeMath.sol";
|
||||
import "../IBridgeValidators.sol";
|
||||
|
||||
contract BaseFeeManager is EternalStorage {
|
||||
using SafeMath for uint256;
|
||||
|
||||
event FeeUpdated(uint256 fee, uint256 fee);
|
||||
event FeeUpdated(uint256 fee);
|
||||
|
||||
function calculateFee(uint256 _value, bool _recover) external view returns(uint256) {
|
||||
uint256 fee = getFee();
|
||||
|
@ -15,22 +16,50 @@ contract BaseFeeManager is EternalStorage {
|
|||
if (!_recover) {
|
||||
return _value.mul(fee).div(eth);
|
||||
}
|
||||
return _value.mul(fee).div(eth.sub(fee)); // value * fee / (1 ether - fee)
|
||||
}
|
||||
|
||||
function distributeFeeFromSignatures(uint256 _fee) external {
|
||||
}
|
||||
|
||||
function distributeFeeFromAffirmation(uint256 _fee) external {
|
||||
return _value.mul(fee).div(eth.sub(fee));
|
||||
}
|
||||
|
||||
function setFee(uint256 _fee) external {
|
||||
uint256 fee = _fee.mul(1 ether);
|
||||
uintStorage[keccak256(abi.encodePacked("fee"))] = fee;
|
||||
emit FeeUpdated(_fee, fee);
|
||||
uintStorage[keccak256(abi.encodePacked("fee"))] = _fee;
|
||||
emit FeeUpdated(_fee);
|
||||
}
|
||||
|
||||
function getFee() public view returns(uint256) {
|
||||
return uintStorage[keccak256(abi.encodePacked("fee"))];
|
||||
}
|
||||
|
||||
function distributeFeeFromAffirmation(uint256 _fee) external {
|
||||
distributeFeeProportionally(_fee, true);
|
||||
}
|
||||
|
||||
function distributeFeeFromSignatures(uint256 _fee) external {
|
||||
distributeFeeProportionally(_fee, false);
|
||||
}
|
||||
|
||||
function distributeFeeProportionally(uint256 _fee, bool _isAffirmation) internal {
|
||||
IBridgeValidators validators = validatorContract();
|
||||
address [] memory validatorList = validators.validatorList();
|
||||
uint256 feePerValidator = _fee.div(validatorList.length);
|
||||
|
||||
for (uint256 i = 0; i < validatorList.length; i++) {
|
||||
address rewardAddress = validators.getValidatorRewardAddress(validatorList[i]);
|
||||
onFeeDistribution(rewardAddress, feePerValidator, _isAffirmation);
|
||||
}
|
||||
}
|
||||
|
||||
function onFeeDistribution(address _rewardAddress, uint256 _fee, bool _isAffirmation) internal {
|
||||
if (_isAffirmation) {
|
||||
onAffirmationFeeDistribution(_rewardAddress, _fee);
|
||||
} else {
|
||||
onSignatureFeeDistribution(_rewardAddress, _fee);
|
||||
}
|
||||
}
|
||||
|
||||
function onAffirmationFeeDistribution(address _rewardAddress, uint256 _fee) internal;
|
||||
|
||||
function onSignatureFeeDistribution(address _rewardAddress, uint256 _fee) internal;
|
||||
|
||||
function validatorContract() public view returns(IBridgeValidators) {
|
||||
return IBridgeValidators(addressStorage[keccak256(abi.encodePacked("validatorContract"))]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,19 +72,23 @@ contract BasicHomeBridge is EternalStorage, Validatable {
|
|||
setNumMessagesSigned(hashMsg, markAsProcessed(signed));
|
||||
emit CollectedSignatures(msg.sender, hashMsg, reqSigs);
|
||||
|
||||
IFeeManager feeManager = feeManagerContract();
|
||||
address feeManager = feeManagerContract();
|
||||
if (feeManager != address(0)) {
|
||||
address receipt;
|
||||
uint256 amount;
|
||||
bytes32 txHash;
|
||||
address contractAddress;
|
||||
(recipient, amount, txHash, contractAddress) = Message.parseMessage(message);
|
||||
uint256 fee = feeManager.delegatecall(abi.encodeWithSignatures("calculateFee(uint256,bool)", amount, true));
|
||||
feeManager.delegatecall(abi.encodeWithSignature("distributeFeeFromSignatures(uint256)", fee));
|
||||
handleSignatureFeeDistribution(feeManager, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleSignatureFeeDistribution(address feeManager, bytes message) internal {
|
||||
address recipient;
|
||||
uint256 amount;
|
||||
bytes32 txHash;
|
||||
address contractAddress;
|
||||
(recipient, amount, txHash, contractAddress) = Message.parseMessage(message);
|
||||
uint256 fee = calculateFee(amount, true, feeManager);
|
||||
feeManager.delegatecall(abi.encodeWithSignature("distributeFeeFromSignatures(uint256)", fee));
|
||||
}
|
||||
|
||||
function setMessagesSigned(bytes32 _hash, bool _status) internal {
|
||||
boolStorage[keccak256(abi.encodePacked("messagesSigned", _hash))] = _status;
|
||||
}
|
||||
|
@ -156,4 +160,40 @@ contract BasicHomeBridge is EternalStorage, Validatable {
|
|||
function requiredMessageLength() public pure returns(uint256) {
|
||||
return Message.requiredMessageLength();
|
||||
}
|
||||
|
||||
function feeManagerContract() public view returns(address) {
|
||||
return addressStorage[keccak256(abi.encodePacked("feeManagerContract"))];
|
||||
}
|
||||
|
||||
function setFeeManagerContract(address _feeManager) public onlyOwner {
|
||||
require(_feeManager == address(0) || isContract(_feeManager));
|
||||
addressStorage[keccak256(abi.encodePacked("feeManagerContract"))] = _feeManager;
|
||||
}
|
||||
|
||||
function isContract(address _addr) internal view returns (bool)
|
||||
{
|
||||
uint length;
|
||||
assembly { length := extcodesize(_addr) }
|
||||
return length > 0;
|
||||
}
|
||||
|
||||
function calculateFee(uint256 _value, bool _recover, address _impl) internal view returns(uint256) {
|
||||
uint256 fee;
|
||||
assembly {
|
||||
let ptr := mload(0x40)
|
||||
|
||||
calldatacopy(ptr, 0, calldatasize)
|
||||
|
||||
let result := delegatecall(gas, _impl, ptr, calldatasize, 0, 0)
|
||||
|
||||
mstore(0x40, add(ptr, returndatasize))
|
||||
returndatacopy(ptr, 0, returndatasize)
|
||||
|
||||
switch result
|
||||
case 0 { revert(ptr, returndatasize) }
|
||||
default { fee := ptr }
|
||||
}
|
||||
|
||||
return fee;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,70 +2,20 @@ pragma solidity 0.4.24;
|
|||
|
||||
import "../BaseFeeManager.sol";
|
||||
import "../Validatable.sol";
|
||||
import "../../libraries/SafeMath.sol";
|
||||
import "../../IBridgeValidators.sol";
|
||||
import "../../IBlockReward.sol";
|
||||
|
||||
contract FeeManagerErcToNative is BaseFeeManager, Validatable {
|
||||
using SafeMath for uint256;
|
||||
|
||||
function distributeFeeFromAffirmation(uint256 _fee) external {
|
||||
// TODO: decide whether distribute by stake or proportionally
|
||||
distributeFeeFromAffirmationProportionally(_fee);
|
||||
function blockRewardContract() internal view returns(IBlockReward) {
|
||||
return IBlockReward(addressStorage[keccak256(abi.encodePacked("blockRewardContract"))]);
|
||||
}
|
||||
|
||||
function distributeFeeFromSignatures(uint256 _fee) external {
|
||||
// TODO: decide whether distribute by stake or proportionally
|
||||
distributeFeeFromSignatureProportionally(_fee);
|
||||
}
|
||||
|
||||
//
|
||||
// Distribute Proportionally
|
||||
//
|
||||
function distributeFeeFromAffirmationProportionally(uint _fee) private {
|
||||
uint256 feePerValidator = proportionalFee();
|
||||
address nextValidator = validators.getNextValidator(validators.F_ADDR());
|
||||
|
||||
while (nextValidator != validators.F_ADDR()) {
|
||||
address rewardAddress = validators.getValidatorRewardAddress(nextValidator);
|
||||
require(rewardAddress != address(0));
|
||||
blockReward.addExtraReceiver(feePerValidator, rewardAddress);
|
||||
nextValidator = validators.getNextValidator(nextValidator);
|
||||
}
|
||||
}
|
||||
|
||||
function distributeFeeFromSignatureProportionally(uint _fee) private {
|
||||
uint256 feePerValidator = proportionalFee();
|
||||
address nextValidator = validators.getNextValidator(validators.F_ADDR());
|
||||
|
||||
while (nextValidator != validators.F_ADDR()) {
|
||||
address rewardAddress = validators.getValidatorRewardAddress(nextValidator);
|
||||
require(rewardAddress != address(0));
|
||||
rewardAddress.send(feePerValidator);
|
||||
nextValidator = validators.getNextValidator(nextValidator);
|
||||
}
|
||||
}
|
||||
|
||||
function proportionalFee() private returns(uint256) {
|
||||
IBridgeValidators validators = validatorContract();
|
||||
function onAffirmationFeeDistribution(address _rewardAddress, uint256 _fee) internal {
|
||||
IBlockReward blockReward = blockRewardContract();
|
||||
uint256 validatorsCount = validators.validatorCount();
|
||||
uint256 feePerValidator = _fee.div(validatorsCount);
|
||||
return feePerValidator;
|
||||
blockReward.addExtraReceiver(_fee, _rewardAddress);
|
||||
}
|
||||
|
||||
//
|
||||
// Distribute By Stake
|
||||
//
|
||||
function distributeFeeFromSignatureByStake(uint _fee) private {
|
||||
// TODO: implement fee distribution from signature by stake
|
||||
}
|
||||
|
||||
function distributeFeeFromAffirmationByStake(uint _fee) private {
|
||||
// TODO: implement fee distribution from affirmation by stake
|
||||
}
|
||||
|
||||
function stakeBasedFee(address _validator) private returns(uint256) {
|
||||
// TODO: calculate fee for _validator based on its stake
|
||||
function onSignatureFeeDistribution(address _rewardAddress, uint256 _fee) internal {
|
||||
_rewardAddress.send(_fee);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,9 +21,9 @@ contract HomeBridgeErcToNative is EternalStorage, BasicBridge, BasicHomeBridge {
|
|||
require(msg.value <= totalMinted.sub(totalBurntCoins()));
|
||||
setTotalSpentPerDay(getCurrentDay(), totalSpentPerDay(getCurrentDay()).add(msg.value));
|
||||
uint256 valueToTransfer = msg.value;
|
||||
IFeeManager feeManager = feeManagerContract();
|
||||
address feeManager = feeManagerContract();
|
||||
if (feeManager != address(0)) {
|
||||
uint256 fee = feeManager.delegateCall(abi.encodeWithSignature("calculateFee(uint256,bool)", valueToTransfer, false));
|
||||
uint256 fee = calculateFee(valueToTransfer, false, feeManager);
|
||||
valueToTransfer = valueToTransfer - fee;
|
||||
}
|
||||
setTotalBurntCoins(totalBurntCoins().add(valueToTransfer));
|
||||
|
@ -82,9 +82,9 @@ contract HomeBridgeErcToNative is EternalStorage, BasicBridge, BasicHomeBridge {
|
|||
require(blockReward != address(0));
|
||||
uint256 valueToMint = msg.value;
|
||||
|
||||
IFeeManager feeManager = feeManagerContract();
|
||||
address feeManager = feeManagerContract();
|
||||
if (feeManager != address(0)) {
|
||||
uint256 fee = feeManager.delegatecall(abi.encodeWithSignature("calculateFee(uint256,bool)", valueToMint, false));
|
||||
uint256 fee = calculateFee(valueToMint, false, feeManager);
|
||||
feeManager.delegatecall(abi.encodeWithSignature("distributeFeeFromAffirmation(uint256)", fee));
|
||||
valueToMint = valueToMint - fee;
|
||||
}
|
||||
|
@ -100,4 +100,12 @@ contract HomeBridgeErcToNative is EternalStorage, BasicBridge, BasicHomeBridge {
|
|||
function setTotalBurntCoins(uint256 _amount) internal {
|
||||
uintStorage[keccak256(abi.encodePacked("totalBurntCoins"))] = _amount;
|
||||
}
|
||||
|
||||
function setFee(uint256 _fee) external onlyOwner {
|
||||
require(feeManagerContract().delegatecall(abi.encodeWithSignature("setFee(uint256)", _fee)));
|
||||
}
|
||||
|
||||
function getFee() public view returns(uint256) {
|
||||
return uintStorage[keccak256(abi.encodePacked("fee"))];
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue