diff --git a/contracts/Exchange.sol b/contracts/Exchange.sol index 707bf5c..142c996 100644 --- a/contracts/Exchange.sol +++ b/contracts/Exchange.sol @@ -13,13 +13,10 @@ contract Exchange is Ownable, ExchangeInterface { address constant public ETH = 0x0; - uint256 constant public MAX_FEE = 5000000000000000; // 0.5% ((0.5 / 100) * 10**18) - ExchangeLibrary.Exchange public exchange; - function Exchange(uint _takerFee, address _feeAccount, VaultInterface _vault) public { + function Exchange(address _feeAccount, VaultInterface _vault) public { require(address(_vault) != 0x0); - setFees(_takerFee); setFeeAccount(_feeAccount); exchange.vault = _vault; } @@ -144,13 +141,6 @@ contract Exchange is Ownable, ExchangeInterface { return exchange.fills[hash]; } - /// @dev Sets the taker fee. - /// @param _takerFee New taker fee. - function setFees(uint _takerFee) public onlyOwner { - require(_takerFee <= MAX_FEE); - exchange.takerFee = _takerFee; - } - /// @dev Sets the account where fees will be transferred to. /// @param _feeAccount Address for the account. function setFeeAccount(address _feeAccount) public onlyOwner { diff --git a/contracts/Fees/FeeInterface.sol b/contracts/Fees/FeeInterface.sol new file mode 100644 index 0000000..059eedb --- /dev/null +++ b/contracts/Fees/FeeInterface.sol @@ -0,0 +1,7 @@ +pragma solidity ^0.4.18; + +interface FeeInterface { + + function fees(address user) external view returns (uint); + +} diff --git a/contracts/Fees/FeeManager.sol b/contracts/Fees/FeeManager.sol new file mode 100644 index 0000000..0edbcf1 --- /dev/null +++ b/contracts/Fees/FeeManager.sol @@ -0,0 +1,25 @@ +pragma solidity ^0.4.18; + +import "./FeeInterface.sol"; +import "./../Ownership/Ownable.sol"; + +contract FeeManager is Ownable, FeeInterface { + + uint256 constant public MAX_FEE = 5000000000000000; // 0.5% ((0.5 / 100) * 10**18) + + mapping (uint => uint) public tiers; + mapping (address => uint) public level; + + function setTier(uint tier, uint fee) external onlyOwner { + require(fee <= MAX_FEE); + tiers[tier] = fee; + } + + function setUserLevel(address user, uint tier) external onlyOwner { + level[user] = tier; + } + + function fees(address user) external view returns (uint) { + return tiers[level[user]]; + } +} diff --git a/contracts/Libraries/ExchangeLibrary.sol b/contracts/Libraries/ExchangeLibrary.sol index ac60775..a5d4201 100644 --- a/contracts/Libraries/ExchangeLibrary.sol +++ b/contracts/Libraries/ExchangeLibrary.sol @@ -5,11 +5,13 @@ import "./SafeMath.sol"; import "@dexyproject/signature-validator/contracts/SignatureValidator.sol"; import "./../Vault/VaultInterface.sol"; import "./../HookSubscriber.sol"; +import "./../Fees/FeeInterface.sol"; library ExchangeLibrary { using SafeMath for *; using OrderLibrary for OrderLibrary.Order; + using ExchangeLibrary for ExchangeLibrary.Exchange; event Traded( bytes32 indexed hash, @@ -23,7 +25,7 @@ library ExchangeLibrary { struct Exchange { VaultInterface vault; - uint takerFee; + FeeInterface feeManager; address feeAccount; mapping (address => mapping (bytes32 => bool)) orders; mapping (bytes32 => uint) fills; @@ -61,7 +63,7 @@ library ExchangeLibrary { require(self.vault.balanceOf(order.takerToken, taker) >= fillAmount); uint makeAmount = order.makerTokenAmount.mul(fillAmount).div(order.takerTokenAmount); - uint tradeTakerFee = makeAmount.mul(self.takerFee).div(1 ether); + uint tradeTakerFee = self.calculateFee(makeAmount, taker); if (tradeTakerFee > 0) { self.vault.transfer(order.makerToken, order.maker, self.feeAccount, tradeTakerFee); @@ -165,4 +167,18 @@ library ExchangeLibrary { return remainder.mul(1000000).div(numerator.mul(target)); } + + /// @dev Returns the fee for a specific amount. + /// @param self Exchange storage. + /// @param takeAmount Amount of order to be taken. + /// @param taker Address of the taker. + /// @return Fee amount. + function calculateFee(Exchange storage self, uint takeAmount, address taker) internal view returns (uint) { + uint feeAmount = self.feeManager.fees(taker); + if (feeAmount == 0) { + return 0; + } + + return takeAmount.mul(feeAmount).div(1 ether); + } } diff --git a/test/TestExchange.js b/test/TestExchange.js index e2b7f2c..4b20c84 100644 --- a/test/TestExchange.js +++ b/test/TestExchange.js @@ -28,7 +28,7 @@ contract('Exchange', function (accounts) { web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:7545/")); vault = await Vault.new(erc820Registry.$address); - exchange = await Exchange.new(2500000000000000, feeAccount, vault.address); + exchange = await Exchange.new(feeAccount, vault.address); await vault.addSpender(exchange.address) });