mirror of
https://github.com/embarklabs/embark.git
synced 2025-01-28 14:34:48 +00:00
126 lines
4.9 KiB
Solidity
126 lines
4.9 KiB
Solidity
pragma solidity >=0.5.0 <0.6.0;
|
|
|
|
import "../token/ERC20Token.sol";
|
|
import "../token/SafeTransfer.sol";
|
|
import "../common/Ownable.sol";
|
|
import "../common/ReentrancyGuard.sol";
|
|
|
|
/**
|
|
* @title Fee utilities
|
|
* @dev Fee registry, payment and withdraw utilities.
|
|
*/
|
|
contract Fees is Ownable, ReentrancyGuard, SafeTransfer {
|
|
address payable public feeDestination;
|
|
uint public feeMilliPercent;
|
|
mapping(address => uint) public feeTokenBalances;
|
|
mapping(uint => bool) public feePaid;
|
|
|
|
event FeeDestinationChanged(address payable);
|
|
event FeeMilliPercentChanged(uint amount);
|
|
event FeesWithdrawn(uint amount, address token);
|
|
|
|
/**
|
|
* @param _feeDestination Address to send the fees once withdraw is called
|
|
* @param _feeMilliPercent Millipercent for the fee off teh amount sold
|
|
*/
|
|
constructor(address payable _feeDestination, uint _feeMilliPercent) public {
|
|
feeDestination = _feeDestination;
|
|
feeMilliPercent = _feeMilliPercent;
|
|
}
|
|
|
|
/**
|
|
* @dev Set Fee Destination Address.
|
|
* Can only be called by the owner of the contract
|
|
* @param _addr New address
|
|
*/
|
|
function setFeeDestinationAddress(address payable _addr) external onlyOwner {
|
|
feeDestination = _addr;
|
|
emit FeeDestinationChanged(_addr);
|
|
}
|
|
|
|
/**
|
|
* @dev Set Fee Amount
|
|
* Can only be called by the owner of the contract
|
|
* @param _feeMilliPercent New millipercent
|
|
*/
|
|
function setFeeAmount(uint _feeMilliPercent) external onlyOwner {
|
|
feeMilliPercent = _feeMilliPercent;
|
|
emit FeeMilliPercentChanged(_feeMilliPercent);
|
|
}
|
|
|
|
/**
|
|
* @dev Release fee to fee destination and arbitrator
|
|
* @param _arbitrator Arbitrator address to transfer fee to
|
|
* @param _value Value sold in the escrow
|
|
* @param _isDispute Boolean telling if it was from a dispute. With a dispute, the arbitrator gets more
|
|
*/
|
|
function _releaseFee(address payable _arbitrator, uint _value, address _tokenAddress, bool _isDispute) internal reentrancyGuard {
|
|
uint _milliPercentToArbitrator;
|
|
if (_isDispute) {
|
|
_milliPercentToArbitrator = 100000; // 100%
|
|
} else {
|
|
_milliPercentToArbitrator = 10000; // 10%
|
|
}
|
|
|
|
uint feeAmount = _getValueOffMillipercent(_value, feeMilliPercent);
|
|
uint arbitratorValue = _getValueOffMillipercent(feeAmount, _milliPercentToArbitrator);
|
|
uint destinationValue = feeAmount - arbitratorValue;
|
|
|
|
if (_tokenAddress != address(0)) {
|
|
ERC20Token tokenToPay = ERC20Token(_tokenAddress);
|
|
require(_safeTransfer(tokenToPay, _arbitrator, arbitratorValue), "Unsuccessful token transfer - arbitrator");
|
|
if (destinationValue > 0) {
|
|
require(_safeTransfer(tokenToPay, feeDestination, destinationValue), "Unsuccessful token transfer - destination");
|
|
}
|
|
} else {
|
|
// EIP1884 fix
|
|
(bool success, ) = _arbitrator.call.value(arbitratorValue)("");
|
|
require(success, "Transfer failed.");
|
|
|
|
if (destinationValue > 0) {
|
|
// EIP1884 fix
|
|
(bool success, ) = feeDestination.call.value(destinationValue)("");
|
|
require(success, "Transfer failed.");
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @dev Calculate fee of an amount based in milliPercent
|
|
* @param _value Value to obtain the fee
|
|
* @param _milliPercent parameter to calculate the fee
|
|
* @return Fee amount for _value
|
|
*/
|
|
function _getValueOffMillipercent(uint _value, uint _milliPercent) internal pure returns(uint) {
|
|
// To get the factor, we divide like 100 like a normal percent, but we multiply that by 1000 because it's a milliPercent
|
|
// Eg: 1 % = 1000 millipercent => Factor is 0.01, so 1000 divided by 100 * 1000
|
|
return (_value * _milliPercent) / (100 * 1000);
|
|
}
|
|
|
|
/**
|
|
* @dev Pay fees for a transaction or element id
|
|
* This will only transfer funds if the fee has not been paid
|
|
* @param _from Address from where the fees are being extracted
|
|
* @param _id Escrow id or element identifier to mark as paid
|
|
* @param _value Value sold in the escrow
|
|
* @param _tokenAddress Address of the token sold in the escrow
|
|
*/
|
|
function _payFee(address _from, uint _id, uint _value, address _tokenAddress) internal {
|
|
if (feePaid[_id]) return;
|
|
|
|
feePaid[_id] = true;
|
|
uint feeAmount = _getValueOffMillipercent(_value, feeMilliPercent);
|
|
feeTokenBalances[_tokenAddress] += feeAmount;
|
|
|
|
if (_tokenAddress != address(0)) {
|
|
require(msg.value == 0, "Cannot send ETH with token address different from 0");
|
|
|
|
ERC20Token tokenToPay = ERC20Token(_tokenAddress);
|
|
require(_safeTransferFrom(tokenToPay, _from, address(this), feeAmount + _value), "Unsuccessful token transfer");
|
|
} else {
|
|
require(msg.value == (_value + feeAmount), "ETH amount is required");
|
|
}
|
|
}
|
|
}
|