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

Protocol Fees #42

Closed
hysz opened this issue May 4, 2019 · 10 comments
Closed

Protocol Fees #42

hysz opened this issue May 4, 2019 · 10 comments
Labels
status: implemented Proposed changes have been implemented (and deployed, if smart contract) type: core

Comments

@hysz
Copy link
Contributor

hysz commented May 4, 2019

ZEIP-42

Summary

The stake-based liquidity incentives proposed in ZEIP 31 (#31) specify a protocol fee for each fill executed on the Exchange contract. This proposal defines the fees for each function in the Exchange.

Discussion: ZEIP-42 Discussion.

Fees

Exchange Fees

Each fill on the Exchange contract will incur a static fee that scales linearly with the gas price of the transaction. A multiplier, the protocolFeeMultiplier will be set in the Exchange contract. This multiplier will be multiplied by a transaction’s gas price to calculate the protocol fee that should be paid.

A protocol fee will be paid for each order that is “filled” (even if this is only a partial fill). As an example, a successful call to matchOrders will pay twice as many protocol fees as a successful call to fillOrder because two orders will be filled in the order matching operation. This behavior also applies to batch functions.

The initial proposed value for the protocolFeeMultiplier is 150k, roughly the cost of filling an ERC20 order through the exchange. While this value is not expected to change, it is upgradeable and can be updated after a time-lock has elapsed.

(See original copy of this issue for a chart that outlines the fees on a function-by-function basis. The multiplier that is ultimately selected will replace 110k in this chart).

Fee Assets

The only assets that will be used to pay protocol fees will be ether and ether that has been wrapped by the canonical weth contract (https://etherscan.io/address/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2#code). The inclusion of WETH as a protocol fee asset improves the user and developer experience of using protocol fees in many cases, especially when a contract is interacting with the protocol.

If enough ether is sent to the Exchange contract to pay the protocol fee, the ether will be used to pay the fee. In case there is not enough ether to pay the protocol fee, the staking contract can transfer WETH from the address that called the Exchange contract to pay the protocol fee. If WETH is taken to pay the protocol fee, any ether that was sent to the Exchange contract will be completely refunded.

To use WETH to pay protocol fees, one must first set an allowance for the Staking contract address. Otherwise, ether can be used to pay the fee.

Meta-transactions

The execute and batchExecute functions are also required to pay protocol fees when calling any functions that require protocol fees. If enough ether is sent to the Exchange contract by the sender of the meta-transaction to pay the protocol fee, this ether will actually be used to pay the fee (and the sender will not be refunded by the creator of the meta-transaction). Otherwise, WETH will be taken from the signerAddress of the meta-transaction.

The decision to forego refunding the signerAddress was influenced by the fact that some senders of meta-transactions may intentionally subsidize the protocol fee that must be paid. This mechanism allows fees to be paid by either the sender or the signerAddress.

Charging the signerAddress WETH for protocol fees opened up an attack vector that would allow the sender of meta-transactions to grief the signerAddress out of WETH by submitting transactions with arbitrarily high gas prices. To mitigate this attack, a gasPrice field has been added to the ZeroExTransaction struct. execute and batchExecute will now verify that tx.gasPrice == transaction.gasPrice.

Exception For Order Matching

In the original ZEIP, there was discussion around making an exception for one of the protocol fees in matchOrders for addresses that the exchange contract could identify as a matching relayer. After further discussion, we decided not to include this exception in an effort to reduce the complexity of V1 of the staking contracts.

Notes

  • A fee is only incurred by successful transactions
  • In batch/market functions, each maker is credited with a portion of fee that is proportional to the number of their orders that were filled
  • Any ETH sent to the Exchange contract in excess of the protocol fee is refunded to the sender
  • If too little ETH is sent to the Exchange contract, WETH will be used to pay the protocol fee.
@dekz dekz added the 3.0 label May 6, 2019
@dekz dekz changed the title [3.0] Protocol Fees Protocol Fees May 6, 2019
@satosheth
Copy link

Maybe I am misunderstanding why 110k was chosen, but it is still unclear to me why the standard gas price for fill order is used as the base multiplier. Why not use 55k or 25k? As a relayer I would definitely prefer lower fees per transaction. Obviously there will be a floor value where the fee would be too low to encourage staking or discourage market making, but I haven't read why 110k is ideal. If there is something I missed reading please link me. Otherwise I would vote for cutting those fees in half or at least down to a threshold where market makers would still be happy.

@0xpeter
Copy link

0xpeter commented May 8, 2019

The number 110k was determined with the goal of ensuring an adequate amount of money flows through the system to motivate active participation among MMs and ZRX holders. We set this amount to target an average fee amount of $0.10 per order fill. That might seem like a lot. However, we have to remember that the $0.10 is divided between the market maker who supplied liquidity for the trade and ZRX stakeholders who delegate ZRX to the maker. Paying $0.10 to the MM is quite different from paying $0.10 to the ZRX holder. It is the amount that is removed from the system and paid to the ZRX holder that actually matters.

To see this, we need to look deeper into the system to determine the actual incidence of the fee on traders. Let's start with a simple case. Imagine that each order incurred a fixed fee of $0.10 and that 100% of this $0.10 charge was paid to the maker. Under this system, we would expect the maker to pass on all of the fee revenue he collects to the taker in the form of price discount. Since the maker now receives $0.10 more from an order fill, he should be willing to discount the order's asking price by exactly $0.10.

To recap, the taker pays an extra $0.10 fee, but receives a $0.10 price discount. The maker charges $0.10 less, but receives a $0.10 fee rebate. We can see the taker is paying exactly the same amount as he had been prior to the introduction of the fee. Likewise, the maker is receiving exactly the same amount as he had been prior to the introduction of the fee. Absent some additional constraint that prevents the maker from offering such a discount, we should not expect fee structures like this to have any real affect on maker-taker behavior.

In the proposed system, the maker does not receive 100% of the fee revenue. Instead, the equilibrium division of fee revenue between maker and staker is determined by a parameter alpha. We plan to specify alpha such that the maker receives approximately 75% of the fee and stakers receive 25%. The $0.075 amount rebate that the maker receives should be offset by a corresponding discount of $0.075 in the order's asking price, as in the above example. The remaining $0.025 goes to the ZRX holder. This $0.025 per trade is the fee that is actually impactful.

We can assess whether $0.025 per trade is a small or large amount in various ways. One way of benchmarking this is through comparison to other fees the taker is paying. Recall that the taker is paying the miner a full $0.10 for use of the Ethereum blockchain. On top of this, he would now be paying $0.025 for use of the 0x protocol. In my view, collecting 25% of total transaction processing costs as a protocol fee is very reasonable. We should not expect such a small addition on top of what people are currently paying to significantly affect user behavior.

We can also assess whether this fee is small or large by considering it in terms of a percent of traded volume. On a $100 trade, the fee is mere 0.025% of the exchanged volume. On a $1,000 trade, it is a mere 0.0025% of exchanged volume. Relative to CEX fees or the spreads users are currently paying to access liquidity on decentralized exchanges, these fees are tiny. If a user is currently paying a 0.3-0.5 % half-spread to access liquidity, we should not expect an additional 0.0025-0.025% charge to be an impetus to move his trades to another platform. The number we really need to worry about is the 0.3-0.5% half-spread. To encourage more usage, we need to drive this cost down, so as to improve the protocol's overall value proposition.

Finally, one might say maybe that is all true, but why can't we charge even less? We aren't planning to begin using this program to fund development in the near-term, so why start charging $0.10 now. Well in order to actually test out the proposed system, we need to ensure that enough money is at stake that it will be worthwhile for market makers and ZRX holders to participate in the system. Given current trade volumes on ZRX relayers, collection of $0.025 per trade seems to approach the bare minimum necessary to ensure ZRX holder participation.

@polezo
Copy link

polezo commented May 8, 2019

That might seem like a lot. However, we have to remember that the $0.10 is divided between the market maker who supplied liquidity for the trade and ZRX stakeholders who delegate ZRX to the maker.

@0xpeter will the Community Development Fund also receive a small share of the fees as specified in 2.4.4 of ZEIP 31 and the blog post? Or has that aspect of the fee distribution been de-prioritized for now in favor of higher rewards for MMs & Delegators?

Nevermind, I just watched last month's ecosystem call and I now gather that the community fund comes from the likely inbalance in the Cobb-Douglas production function. Very interesting

@PhABC
Copy link
Contributor

PhABC commented May 9, 2019

Thanks for putting together, a fee structure that is very reasonable for medium and high-value trades. However, I do have one concern, and it's a significant one for us. For www.skyweaver.net (and other games I assume), many of our assets will be valued at 1$ each, or less, and we expect players to purchase one or two assets on a frequent basis.

Assuming the cost of 1155 trades is similar to ERC-20 trades, i.e. 110k, gas and assuming the protocol fee is also 110k gas based on current proposal, then at 5 GWei of fee (ETH@$170), the cost of a trade just in gas fee + protocol fee would be 0.19$. At gas price of 20 Gwei, the cost would be 0.75$, which is 75% of the asset's value.

Trading low-value assets is already expensive with 0x without ZEIP-42 (compared to Uniswap for example), but now with this proposal low-value assets trades become impractical. I am not sure how we can sustain such fees without a) sacrificing our profits as a Relayer, b) making our assets 2-3x more expensive (impacting accessibility to the game) or c) hedging with gas tokens.

@hysz
Copy link
Contributor Author

hysz commented May 15, 2019

@PhABC I spoke with some folks on our team and if I understand your model correctly, skyweaver is serving as both the relayer and maker; is that correct? In this case, you could open a staking pool to offset the fee or even earn a net profit (see ZEIP #31).

As Peter mentioned above, 75% of the fee goes to the maker and 25% to stakers. To use your example of 5 GWei: the protocol fee would be 9.5¢, with 7.1¢ going to you (the maker) and 2.4¢ to stakers. By staking, you'll recapture a portion of this 2.4¢/trade (aggregated across all makers) that is proportional to your stake.

@abandeali1
Copy link
Member

@PhABC I understand that this could add a significant percentage premium to smaller trades, but wanted to make a couple points:

  • If this is a huge problem, then it is likely gas fees alone will become a large issue for you at some point. The protocol fee won't actually change how total fees scale with gasPrice (O(n) vs O(2n) doesn't really matter in the long run).
  • If an order is selling batches of tokens, either via the MultiAssetProxy or ERC1155Proxy, you will still only be charged a single fee.

@0xpeter
Copy link

0xpeter commented May 16, 2019

The protocol fee won't actually change how total fees scale with gasPrice (O(n) vs O(2n) >doesn't >really matter in the long run).

Since 75% of the protocol fee is rebated to the maker, the comparison is really O(n) vs O(1.25n).

Status Quo: Maker offering to sell an item at $1 price with a ~$0.10 gas fee.
New case: Maker offering to sell item at $0.925 price with a ~$0.10 gas fee + ~$0.10 protocol fee.
The maker gets rebated $0.075 when the item sells, so he is still receiving $1.
The taker is paying $1.125 total instead of $1.1, so he is bearing an added cost of $0.025.

The bigger picture issue is finding some way of scaling these trades (via batching or otherwise), so that you are not paying a 10% gas fee every time a low value NFT changes hands.

@laurengarcia
Copy link

laurengarcia commented May 18, 2019

Thanks for this discussion. Any estimates on the impact of ZKPs on transaction fees in the future, esp w/r/t batched transactions ?

@laurengarcia
Copy link

laurengarcia commented May 18, 2019

Also want to echo support for figuring out @0xpeter 's last comment: The bigger picture issue is finding some way of scaling these trades (via batching or otherwise), so that you are not paying a 10% gas fee every time a low value NFT changes hands.

^^ This is super important to figure out for the use-case of spinning up a mesh network of relayers and letting them earn passive income on small NFT transactions at scale.

@PhABC
Copy link
Contributor

PhABC commented May 22, 2019

@hysz

As Peter mentioned above, 75% of the fee goes to the maker and 25% to stakers

So the total cost for a maker-relayer would effectively be < 27.5k extra gas, depending on how much ZRX is staked.

@abandeali1

If this is a huge problem, then it is likely gas fees alone will become a large issue for you at some point. The protocol fee won't actually change how total fees scale with gasPrice (O(n) vs O(2n) doesn't really matter in the long run).

I think that's only true if gas price is very high. 0.5$ vs 1$ is a significant difference if the asset is of 1$ value.

If an order is selling batches of tokens, either via the MultiAssetProxy or ERC1155Proxy, you will still only be charged a single fee.

That's good, I haven't noticed that case. Our implementation already reduces transfer cost of multiple tokens by about 60-80% compared to single token transfers, so we were already going to encourage trading batches of assets.

@0xpeter

The bigger picture issue is finding some way of scaling these trades (via batching or otherwise), so that you are not paying a 10% gas fee every time a low value NFT changes hands.

Yes, in our case it seems like with batchTransfers, we reduce protocol fee cost and transfer gas cost. We will have incentives into place to encourage this kind of behavior on our marketplace.

@dekz dekz mentioned this issue Oct 21, 2019
@mintcloud mintcloud added status: implemented Proposed changes have been implemented (and deployed, if smart contract) type: core and removed type: core 3.0 labels Apr 10, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: implemented Proposed changes have been implemented (and deployed, if smart contract) type: core
Projects
None yet
Development

No branches or pull requests

9 participants