-
Notifications
You must be signed in to change notification settings - Fork 15
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
Fee splitting between relayers ; Affiliate program #12
Comments
Note that in the current real world, affiliates are not imposed on costumers. Affiliate URLs are very common and everybody can change the URL to their own affiliate link. Changelly, for example, allow anyone to become an affiliate, which allows you to have reduced fees when you use your own referral link. Considering the affiliate market is valued in the billions of dollar, I believe these approaches are viable options. Improvements can definitely be made, but, in my opinion, should never impair user experience . |
My comments: I really like the affiliate term in this context, with the original relayer being the primary relay and the secondary ones being affiliates. I'm not too fond of the non-enforceability aspect of 1, but I like the idea of a relayer explicitly opting into several affiliates with a specified split. This opens the door for dynamic splits that rewards more productive affiliates. State channels are also an interesting approach in 2, but I'm a little weary of how much of this logic would live outside of the protocol and escape standardization. I'd like to pitch in a variant to your approach 1. This is probably very gas heavy, but I think it would address enforceability and also keep your core ideas of setting downstream fee splits. Alice makes her original order at Relayer A, with them as the fee recipient. The basic order format is the same as it is today, and the order hash / her signature still covers the same parameters, including one fee recipient and the total maker and taker fees. The difference is that the call to For example, when originally posted on Relayer A, the relay fee related parameters are:
Let's say Relayer B requests to share Alice's order from Relayer A, and Relayer A decides the maker and taker fee split based on the history of their relationship. Relayer A would respond to Relayer B with the following parameters:
Note that the first relay signature now omits the order salt in its coverage. The exchange contract will use it for verification, but won't allow it for taking an order. Also, Relayer A will supply Relayer B with Now, let's say that Relayer B would like to share Alice's order with Relayer C. Relayer B would be allowed to sign off some of its fees to Relayer C, but no more than it would receive in total:
Relayer B would also provide Relayer C with Finally, let's say Relayer C shares this order with Relayer D:
Again, Relayer C will provide Relayer D with If Bob were to discover this order on Relayer D and take it, the exchange contract would verify that the maker and taker fees decrease monotonically and that each relay signature belongs to the preceding address. The fee recipients would get paid out backwards in the table, each row subtracting the accumulated fees of prior rows. For example, for the Maker Fee, Relayer D would get 0.5 ZRX, Relayer C would get 0.5 ZRX (1 - 0.5), Relayer B would get 1 ZRX (2 - 1), Relayer A would get 3 ZRX (5 - 2), which sum to the total maker fee of 5 ZRX. Alice and Bob still pay no more than the original maker and taker fees, respectively. The order Bob receives from Relayer D intentionally omits the previous relay signatures that cover the order salt, so Bob cannot shortchange any relayers in the chain. For example, Bob could not fill the original order paying out all the fees to Relayer A, because he doesn't have its relay signature that covers the order salt. (He could, of course, go to straight to Relayer A, but he could have always done that.) Intermediate relayers cannot forge the fees, as they can't sign the updated hash that covers them. The added costs are as many signature verifications as there are relayers, more complex fee calculations, and more input data in the transaction. This is all obviously expensive in terms of gas, but it would allow for trustless relaying with downstream fee splitting, while only modifying or introducing a variant of edit: fix typos |
I think @vsergeev's solution adds a lot of complexity and gas while not actually solving much. If a user is going to go to the effort of circumventing the affiliate's application, they already have the order hash and the base feeRecipient. It seems like it wouldn't take much extra effort to map the feeRecipient address back to the source relayer, then go directly to the source to get the order (given the order hash) without any affiliate signatures. I think a simpler solution is to have the order define an affiliateFee to come out of total fee (makerFee + takerFee). If an affiliateFee is specified, but no affiliate is provided when the transaction is filled, pay the affiliate fee to the feeRecipient, but do it in two separate transactions through the token transfer proxy to ensure that gas can't be saved by not specifying an affiliate address. This doesn't directly allow the relayer to specify different fees for different affiliates, but that's solvable too. At OpenRelay, we're developing an affiliate contract to split received fees between us and our affiliates (though without this ZEIP we're only able to split fees with the affiliate that helps create transactions, not with affiliates that help fill transactions). If a relayer wants to give different shares to different affiliates, they could have the accepted affiliate addresses be contracts that will split the affiliate fees according to different percentages for different affiliates. I must admit my knowledge of gas consumption is somewhat limited, and it seems plausible that the EVM might reduce the gas for multiple updates to the same addresses to look like a single update, in which case this solution may not pan out. |
@AusIV, the complexity is not just mitigating user circumvention, but it's also to support chained affiliates, while preventing them from stealing fees they're not entitled to. If we're only concerned with one affiliate, it could be simplified. I just don't think the exchange contract is the right place to store affiliate relationship state -- that seems like it should be offchain. I do like your idea of paying fees to a contract that splits between relayer and affiliate(s), but I think there are still some difficulties with supporting multiple affiliates, not to mention chained affiliates, without asking the maker to re-sign for each one. Maybe a hybrid option is that there could be a formalized fee split contract interface, which the exchange contract could edit: rename affiliate token to affiliate id to avoid confusion |
I guess I'm not convinced of the need for affiliate chaining. I can see it being mildly useful, but I don't see it being valuable enough to justify the complexity. Another issue with that proposal is that feeRecipients must be key pairs for that to work, and can't be contracts. Not only that, the private keys have to be on live, connected systems to be able to sign orders for specific affiliates. I'm fairly intent on keeping the keys that can withdraw my relay funds as isolated as possible, so having to have them on the system serving my orderbook rubs me the wrong way. (It doesn't help that I spent the afternoon consoling a friend who lost his life savings because his bitcoin private keys got stolen from a system that was supposed to be secure). |
I'm excited to hear you guys have opened the floor for discussion on the subject of fee splitting between collaborating relayers, as it makes all the sense in the world if you really want the relayer protocol to gain momentum. I'm not familiar with state channels so option 2 is a bit beyond my grasp at this stage, but with regards to option 1 I will just say that I'm a pragmatic entrepreneur/dev, and not too worried at this stage about the possibility of bad actors skimming a few affiliate fees here and there. I don't expect the affiliate fees to be particularly large since the relayer will likely be taking the lions share, as such bad actors can't get away with a whole lot before they're spotted and mitigated. The gas argument on option 1 is fair but honestly, from a consumer side of it, thanks to relayer liquidity sharing you now have access to much better market deals, and so what's a little more gas expenditure? My advice is don't overthink it and go with something practical, let it loose and see how it performs so you have some tangible data from which to drive the relayer protocol roadmap. The perceived bad actor threat may not really be as much of a threat as you think, and the gas fee may not be as big a deal as you think... the proof is in the pudding :) |
@vsergeev I do like your proposal, especially the signature from the relayer for each of their affiliate to ensure users don't remove it. Producing a signature is cheap computationally wise and relayers would be happy to sign the orders to their affiliate if it means they could earn some profit from their users filling it. I edited 1. to include this. However, as @AusIV mentioned, it might indeed have some security risks that relayers would not be willing to expose themselves to. I do agree with @AusIV however that I am not sure if the multi-layer relayer feature is necessary at the moment. From my experience, I often tend to over-engineer things while trying to solve problems that in practice actually never show up (or ends up being insignificant). We know that allowing at least one affiliate can come a long way, more is unclear. I therefore think a single affiliate-layer is a sufficient proposal for a first version of this affiliate feature. Perhaps in the future we will see that many people requests more than one layer and then we can revisit this proposal. @AusIV Yes, I am pretty sure that updating the same address twice will result in lower gas consumption than updating two separate addresses, and it might be impossible in practice to have the same gas consumption when no or one affiliate is specified. @avonian I do indeed agree with you that in practice most users will not try to remove the affiliate address, especially if some off-chain consequences are applied. In the end, if implemented properly, a user would need to move their funds or find another relayer if they remove the affiliate address, which is more expensive both in time and gas than simply letting the affiliate address on the order. I also do think that this simple solution might be fine for first implementation and refinement can be made in the future, especially since this introduces no substantial security risks for the users and relayers. |
Can we revisit this thread now? The launch of 0x Mesh makes this more relevant for 0x than ever. Other projects are also asking for this in the Discord channels (VeriSafe team). One possible workaround I have been kicking around in my head for this w/r/t Microsponsors is rewarding the 2nd or "affiliate" relayer the new 0x market-maker incentive reward somehow. But certainly the native ability to split the fees would be more efficient as well as easy for the ecosystem of relayers to implement. |
This topic is getting more attention now that mesh nodes are being used. In my opinion, the best way to do this is by using the current forwarder extension with an associated fee and some sort of extension contract extended for the tokens trades. That way, frontend DApps will have benefits to run 0x mesh nodes and display orders from it. |
What’s status of this. Should revisit https://twitter.com/joeykrug/status/1184499195341877249?s=21 |
We're evaluating different models to land affiliate fees - they don't all necessarily require core upgrades to the protocol. For example, these could be added as a takerFee in bridge orders served by 0xAPI |
Summary
The 0x protocol could allow relayers to split the fees with their affiliates if another agent help in the filling of one of their orders.
Motivation
Currently, if an order from relayer Alice is filled by a user from relayer Bob, Alice will receive 100% of the fees. Bob benefits from this since it increases his liquidity, but the incentive is somewhat weak. In addition, there is no incentive for third parties to simply act as order aggregators, since they would never receive fees. Allowing relayers to give part of the fees to their affiliates would create a stronger incentive for relayers to share their liquidity and to borrow orders from others.
In addition of creating stronger collaboration among the 0x network, it can also allow for new, interesting strategies and profitable infrastructure. For instance, some agents could simply aggregate order from all the relayers and offer the best orders available, both price wise and fee wise, to dApps. Such a service would allow dApps to listen to communicate with a much smaller number of relayers and would still be profitable for the agent running this order aggregator system.
Another interesting application would be to create a Reserve Manager based relayer where users can contribute to the liquidity pool by being affiliates. One of the main problem of the Reserve Manager strategy is that the relayer needs large reserves if they want to fill the need of a large amount of users. One obvious solution to this would be for users to deposit their funds in a smart contract and this smart contract acts as a reserve. However, there are some complications when it comes to price control attacks and fair profit sharing. With fee splitting, you can have a simpler approach to this problem ; Liquidity providers can simply create orders at a price requested by the relayer and when these orders are filled, the liquidity provider can receive part of the fees.
Specification
There are multiple ways to allow affiliates on the 0x protocol.
Change the exchange.sol smart contract so that an extra argument
affiliateAddress
can be passed when filling an order. This argument would be outside of the signature and would be appended by the affiliates themselves. The fees could them be split between thefeeRecepient
andaffiliateAddress
at a ratio specified byfeeAffiliate[feeRecepient][affiliateAddress]
. IffeeAffiliate[feeRecepient][affiliateAddress]
returns 0x0, then theaffiliateAddress
was not approved by the relayer atfeeRecepient
. The relayer could sign the order with the affiliate address to prevent users from removing the affiliate address (proposed by @vsergeev).Create a single-party state-channel between affiliates and relayers. Alice is an affiliate and Bob is a relayer. Alice and Bob open a state channel where Bob deposits y ZRX. Alice appends her ETH address as data passed in the order filling transaction sent by her users (or as argument in
fillOrder
which triggers an Event). Alice shows to Bob (or Bob sees) that one of Alice's users filled one of Bob's order and referenced Alice as an affiliate. Bob sends Alice a signed message allowing her to take k ZRX. Alice can then take the latest signed message from Bob to claim her rewards. If Bob doesn't send the signed message, Alice can stop trying to fill Bob's orders or close the channel. If Bob's wants Alice to stop being an affiliate (e.g. Alice is a miner front-running real affiliates), then Bob closes the channel (with a bounty claim period).Rationale
Currently, both suggestions do not force an order to be attached to an affiliate in order to minimize friction from the user perspective (unless relayer sign orders for each affiliate with the affiliate address). Maker or taker would otherwise be required to either resign the order or sign the affiliate address before filling an order, respectively, both of which impair user experience. I believe there are off-chain solutions affiliates and relayers can use to make sure the affiliate reward goes to the right address.
Examining both solutions ;
However, with this solution, there is no need for an external smart contract. You need simple a new mapping variable, 1 new function (
setFeeAffiliate(address affiliateAddress, int value)
), a few lines to perform the fee splitting and adjust certain functions to accepts this new argumentaffiliateAddress
passed when filling an order. In addition, affiliates can blacklist addresses from accessing their API if they notice an address keeps removing them as affiliate. The user would then need to move their funds, which is more expensive than simply paying the affiliate. Other off-chain solution might be possible to make it more expensive for users to not-include the affiliate address than leaving it as is.Here as well, users could remove the
affiliateAddress
from their fillOrder transaction, but now there is no real incentive to do so, since users that aren't affiliate will not earn anything from changing theaffiliateAddress
and that letting thisaffiliateAddress
will not increase the gas cost of filling the order (or only marginally if Event based).Note that modifying approach 2 slightly to act as a handshake between the relayer and affiliate could reduce
fillOrder
collisions. For example Alice (affiliate) says to Bob (relayer) that one of her user will fill Bob's order X, Bob sends the signed message to Alice allowing her to take reward (conditional here), Alice allow her user to fill the order, Alice provides a proof that her user filled the order and claim (perhaps can bundle proofs for each orders) reward. If Alice users don't fill the order, then Bob closes channel. Bob will not send a signed message to other affiliates then Alice, since he would have to pay them all for an order that is already "promised" to be filled by Alice. Alice will wait for the handshake before letting her users fill the order since she will not receive the reward (signed message from Bob) otherwise. This handshake version has flaws, but thinking along these lines might allow relayers and affiliate to handshake before the affiliate's users fill a trade, which could significantly reduce collisions when orders are shared by many relayers (albeit impair communication flow between relayers and affiliates).Summary
In general, allowing fees to be split between relayers and affiliates would not only significantly increase the collaboration within the 0x network, but would also open the door to more many new interesting strategies and ideas.
The text was updated successfully, but these errors were encountered: