-
Notifications
You must be signed in to change notification settings - Fork 45
Implement gas refunds as an interaction. #445
Conversation
It also looks like the maximum number of interactions we can use is ~7: This implies that the smallest overhead per refund is ~700 gas Here are the same benchmarks applied to PR #441 |
One big advantage of using interactions is that all settlement paths can use refunds, and don't pay for them if they aren't used. The 5K gas overhead is quite steep though. |
6b73933
to
b78baa2
Compare
3eaeb48
to
d01704f
Compare
This means that from a gas refund of 15k gas we only get back 2.5k. I was expecting a bit less overhead for a |
I think the refund is technically only 10k as we pay 5k to set the value to 0. I agree that losing 5k here seems a bit much. Can we, with all these measurements, simulate the avg. cost following scenarios:
Then we can decide if returns should be part of the fast path (natively) |
edit: Updated PR deciption with analysis. I think we should merge this change 🚀 |
d01704f
to
a6ac8be
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The analysis makes sense and the code looks good.
The current gas benchmark looks very misleading with 200gas/refund more, I wonder if the 6/7 argument could be in some way included in the benchmark.
["freeFilledAmountStorage", filledAmounts] as const, | ||
["freePreSignatureStorage", preSignatures] as const, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the as const
here for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as const
makes it so the type is [string, BytesLike[]]
instead of (string | BytesLike[])[]
. The as const
is necessary for tuple type inference.
* @param settlement The address of the settlement contract. | ||
* @param orderRefunds The order refunds to encode. | ||
*/ | ||
public encodeOrderRefunds(orderRefunds: Partial<OrderRefunds>): void { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This new line of documentation is not needed.
May not be worth it since these refunds will be obsolete sooner than we think |
I think that makes this change more worth it, as currently we pay a fixed overhead on every settlement even if we don't use refunds. This change makes it so we pay a larger overhead for gas refunds, but only if we make use of them, (and pay less gas when a settlement is made without any refunds). |
Hmm, I'm not sure I understand exactly what you mean. |
This:
and this:
look contradictory to me at first glance. My understanding is that the first reasoning is right but it's not captured by the gas benchmark, in the sense that the benchmark measures something else we are not interested in. |
Ah, I see. The first benchmark is the gas/order for single order settlements, the benchmark is for 50 order settlements. To me this indicates a flat additional cost of The original purpose of this benchmark was to measure that the gas cost decreases linearly with order refunds (which it mostly does). We can add additional benchmarks for computing optimal "continuous gas/order" costs. edit: Addressed in #471 |
3781da6
to
d4d76fa
Compare
cc @fleupold Are you OK with merging this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cc @fleupold
Are you OK with merging this?
This PR modifies the `single` settlement benchmarks to run multiple settlements and simulate batching refunds for optimal order gas refund results. /cc @fedgiac Does this address your concerns from #445 (comment) ### Test Plan `yarn bench:single` ``` === Single Order Gas Benchmarks === --------------+--------------+--------------+-------------- settlements | refunds | gasToken | gas/order --------------+--------------+--------------+-------------- 1 | 0 | 0 | 187285 1 | 1 | 0 | 184666 8 | 8 | 0 | 180509 1 | 4 | 2 | 148431 1 | 0 | 5 | 121983 ```
Closes #442
The idea is to make gas refunds be encoded as interactions instead of being part of the settlement parameters.
Gas Cost Analysis
Native Order Refunds
Interaction Based Order Refunds
Results:
So, as @fleupold mentioned, it would be smarter to accumulate refunds and then use them all at once. This reduces the overall gas cost per order.
In the case of native order refunds, the optimal "refund batch" size to use is 7:
181490
(this is the average cost per order when doing 7 settlements without refunds, and then an 8th settlement with 7 refunds)180467
(this is the average cost per order when doing 6 settlements without refunds, then a 7th settlement with 7 refunds)In the case of interaction based order refunds, the optimal "refund batch" size is 8:
181237
180484
(only 17 gas more)This means that the gas cost per order is almost the same 🎉. One other bonus of keeping order refunds as interactions, is that if, for whatever reason, storage refunds get removed from the EVM, we don't pay additional costs per settlement for a dead feature if we use interaction based storage refunds.
Full Settlements
The full settlement benchmarks show a similar story, where settlements without gas costs become cheaper, and settlements without become more expensive.
Benchmarks
Test Plan
CI, added new unit tests for interaction-only methods. Coverage stays at 100%.