-
Notifications
You must be signed in to change notification settings - Fork 48
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
Modify "claim" function in MerkleLockup to charge an ETH fee #1032
Comments
We should not because the fee is in the dollar value and it can vary on each chain. |
Yeah |
Why do we want to have |
Correct. We should use |
Given that we now have sablier admin as well as the merkle lockup admin, should we replace merkle lockup
Any other ideas? Here is my implementation:
In the source contract, the naming difference is pretty clear and may not lead to confusion to the users.
But in tests, we use cc @sablier-labs/solidity |
I suggest walking on the path of maximum explicitness and going with
Why constants? They should be editable. |
They are editable in the factory contract but not in the Merkle contracts. The reason is that for a new campaign, the creator knows the fee in advance, and it ensures that these fees won't be changed for that particular campaign. The cons of making them editable in merkle Lockup is that admin can change fee in the middle of an active campaign. |
OK, makes sense, I will have another think during the internal audit. |
Why don’t we simplify the implementation by allowing the factory contract to be the caller of the fee action in the Merkle campaigns? This way, we avoid having two "admins" // MerkleBase.sol
address public FACTORY;
constructor() {
FACTORY = msg.sender;
}
function withdrawFees(address to) public {
// Check: the caller is the factory contract.
if (msg.sender != FACTORY) {
revert Errors.CallerNotFactory(FACTORY, msg.sender);
}
// --snip--
}
// MerkleFactory.sol
function withdrawFees(address to, ISablierMerkleBase merkle) onlyAdmin {
merkle.withdrawFees(to);
} @sablier-labs/solidity wdyt? |
or like uniswap v3 does (our Merkle campaign is equivalent to their pool) but i believe the version from above is better |
I like @andreivladbrg's approach. The benefit is that, we can keep |
I just saw this, and I believe this is a feature, not a con. As mentioned in the comment here, I think we should make them editable. To make an analogy, it would be like activating the protocol fee (with the version implemented in |
Good analogy between protocol fee and clam fee. I'd like to share my views on why they are not the same.
|
Great idea to allow only the factory to call the However, I agree with Shub that we should not make the fee editable for airstreams. The only thing I would add is that we may want to charge different campaigns differently. |
Thanks for the fast answer.
Well, I don’t think campaign creators are affected by this, as they’ve already paid the "fee" by funding the campaign.
That's correct, but I am sorry, I don't understand why this argument is relevant to immutability of the fees? It can still be applied to new campaigns that are created after the fee is set in the factory contract.
this is partially correct, as for
how is this going to be possible? the fixed fee made me think, what if we charge a percentage as well? an example: |
Since this is a product design choice, I kindly ask you @sablier-labs/engineers to provide your input: Should claim fees be charged on: |
They absolutely are. Campaign creators are inextricably linked with their claimers. If their claimers cannot claim because of a very high fee set by Sablier, they will go complain to the campaign creator, not us. They will think that the campaign creator set the high fee.
Yes. A small, predictable, fixed fee. Not one that can be set to 1 ETH overnight.
I don't understand why you don't understand? New campaigns are irrelevant to an existing campaign. The point is for all claimers in a campaign to know transparently ahead of time how much they will pay. If we can change the fee, some will pay 0.001 ETH, others 0.1 ETH, others 1 ETH, etc.
You're right, never mind that.
Gas prices are haphazard. They are outside our control and we shouldn't charge our users like this. |
I suggest opening a discussion with the possible designs laid out clearly. |
We can hardcode a constant
Agreed, but as mentioned above, we can hardcode a max fee, so the "very high fee" issue won’t be a problem. Also, I want to point out that we’ve received complaints in the past for mainnet campaigns where the gas fees for the tx were higher than what participants actually received in USD (we can't know in advance what amount will the creators give to recipients). So, this issue exists regardless of whether we have a fee or not. It’s something we can’t predict.
please see again my comment: "why this argument is relevant to immutability of the fees? It can still be applied to new campaigns that are created after the fee is set in the factory contract." - the idea is that the argument exists outside immutability of the fee per se in one campaign The argument that the fee is fixed and not a percentage applies whether the change affects all existing and future campaigns or only future campaigns. For example, for token X, campaigns X1, X2, and X3 were created. For X1, the fee is 0, but for X2 and X3, the fee > 0. X2 and X3 would still suffer of "which might expose users to unexpected high fees if editable" Please lmk if that clarifies my point.
They will know for sure in advance, as we will give a note in the app that we are charging a fee. So this isn't a problem.
(not talking about the fee amounts, as they might not be precise)
you are right, it is better to be fixed |
|
it can be passed at the deployment time, i don't find this as a problem. /// Factory
uint256 public immutable MAX_FEE;
// depending on the chain, we pass 0.01 ETH, 5 MATIC, etc.
constructor(uint256 maxFee) {
MAX_FEE = maxFee;
}
the percentage is in the token set in the stream, as @PaulRBerg said:
|
Let's say you pass 10 MATIC during the deployment time (which is equivalent to $1). And then the price fell by 80% so now 10 MATIC is $0.2. You won't be able to charge users $1 anymore. Alternatively, let's say the price goes up to 10x. So now the max is $10. Contrary to your claim that fixing would eliminate the "very high fee" issue, when the price shoots up to 10x or 100x, the very high fee issue comes back. What matters for us is the dollar value (also mentioned in the original discussion). |
To @andreivladbrg:
There are nuances; it's possible that without the Sablier fee, the gas fee is not greater than the USD value of the stream, but when the Sablier fee is added, the total fee is greater.
It is a problem because they will one day see that there are no fees, and they will be left with the impression that there are no fees. Also, the campaign creator might advertise the airdrop as free to claim.
I very much doubt that that will happen. If users don't care about claiming the airdrop, it means it's a low-value airdrop. The incentive to claim because Sablier might enable fees at some point in the feature is weak.
I'm afraid it doesn't. I didn't understand your follow-up. Could you please reformulate it? |
In any case. I agree with what @maxdesalle said here. It's simply better to not be able to change the fee retroactively. To answer @smol-ninja's concern about the volatility of the token. It's a relatively minor issue. 80% corrections don't happen that often (thankfully!). Airdrop claim windows last a few months on average (AFAIK). So hard-coding is fine. |
There have been some misunderstandings above, which I have clarified on a call with @andreivladbrg. I don't think it's worth re-explaining them in writing given that we have reached an agreement in #1039. |
Rationale
Monetize Airstreams. See https://github.com/sablier-labs/company-discussions/discussions/72.
I have considered alternative designs whereby the fee is relayed to a Sablier pot, but the added gas cost does not seem worth it. The gas cost paid by users may be higher than the fee itself. Instead of making N transfers, we can just retroactively 'sweep up' the fees from the campaigns that have generated significant amounts.
Spec
claim
functionpayable
modifiermsg.value
is at leastsablierFee
sablierFee
of typeuint256
and a settersetSablierFee
that is admin-gatedwithdrawFees
function (check out this example)The text was updated successfully, but these errors were encountered: