8000 feat: add tradingLimit decimal tracking by philbow61 · Pull Request #573 · mento-protocol/mento-core · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat: add tradingLimit decimal tracking #573

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

Draft
wants to merge 2 commits into
base: develop
Choose a base branch
from

Conversation

philbow61
Copy link
Contributor
@philbow61 philbow61 commented Jan 6, 2025

Description

This PR adds decimal tracking to our existing TradingLimits library.
Before, the trading limit state was stored in a Struct with five variables.

struct State {
    uint32 lastUpdated0;
    uint32 lastUpdated1;
    int48 netflow0;
    int48 netflow1;
    int48 netflowGlobal;
  }

Together these 5 take up 208bits (32 + 32 + 48 + 48 + 48). One storage slot takes up 256 bits, meaning the current state does not fill up the entire slot and leaves space for another 48 bits.

The basic idea of this Pr is adding a single int48 that stores the current decimal part of all limit netflows.
Since an int48 can store a max/min of 140737488355327/-140737488355328 our netflows will only have 14 decimal places.

struct State {
    uint32 lastUpdated0;
    uint32 lastUpdated1;
    int48 netflow0;
    int48 netflow1;
    int48 netflowGlobal;
    int48 netflowDecimals;
  }

For our netflows, the actual current netflow is netflow*1e14 + netflowDecimals. Therefore, the verify function was updated to check whether the limits are surpassed on the decimal places.
e.g

Config {
    limit0 = 1_000;
    limit1 = 10_000;
    limitGlobal = 100_000;
    flags = L0&L1≶
  }

State {
    netflow0 = 1_000;
    netflow1 = -10_000 ;
    netflowGlobal = 99_000;
    netflowDecimals = -0.2;
} 

In this scenario, the actual limits with decimals would look like this:

netflow0 - 0.2 = 999.8 -> limit0 not surpassed
netflow1 - 0.2 = -10_000.2 -> limit1 surpassed
netflowGlobal - 0.2 = 98_999.8 -> limitGlobal not surpassed

When L0 is configured, the decimals are reset when timestep0 seconds have passed.

Open Question:
Currently, our trading limits do not account for amounts smaller than 1e4/-1e4.
We could round them to 1e4/-1e4, similar to what we did previously for the unit part.
In both worlds, the gas costs for trading an amount less than 1e4 will be much higher than any benefit from
manipulating the net flow / bypassing the limits.

Other changes

  • n/a

Tested

  • added tests for both the update and the verification changes

@philbow61 philbow61 marked this pull request as ready for review January 6, 2025 10:15
@philbow61 philbow61 requested review from baroooo and bowd January 6, 2025 10:58
Copy link
Contributor
@baroooo baroooo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job! I couldn't find any issues during my review 🦾

however, I feel that this solution is overly complex for its purpose. and also I am not even sure if it achieves the intended gas savings
while packing variables into a struct might save gas in some cases (e.g. reducing storage writes from 3 to 1 when writing the entire struct in our case), the added complexity for calculating decimals seems to outweight the potential benefits at least based on my intuition

I ran a quick gas cost analysis using the simple test test_update_withL0LG_updatesActive. here are the results for the TradingLimits.update function:

  • current deployed implementation: 2119 gas
  • implementation in this PR: 5066 gas

As a comparison, I implemented a simpler version that uses int256 for netFlows, and the same test consumed 951 gas. while this implementation is likely far from perfect and it's untested beyond a single gas cost check, I believe it would not be more expensive to properly implement that than the current proposal.

given the added complexity and the relatively minor gas cost implications, I would strongly prefer going with a simpler implementation.

if ((config.flags & L0) > 0) {
int256 netflow0WithDecimals = int256(self.netflow0) * DECIMAL_ONE + int256(self.netflowDecimals);
int256 limit0WithDecimals = int256(config.limit0) * DECIMAL_ONE;
if (-1 * limit0WithDecimals > netflow0WithDecimals || netflow0WithDecimals > limit0WithDecimals) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit, I would prefer the order to be not changed for readability:
if (netflow0WithDecimals < -1 * limit0WithDecimals || netflow0WithDecimals > limit0WithDecimals)

@@ -110,6 +123,9 @@ library TradingLimits {
if (config.flags & LG == 0) {
self.netflowGlobal = 0;
}
if (config.flags & (L0 | LG) == 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would make more sense to reset the decimals for every reset for simplicity, considering it will be called infrequently and only downside in losing some decimals. wdyt?

@philbow61
Copy link
Contributor Author

@bowd Baran and I did some additional gas comparison testing yesterday this is what we found:
We tested this implementation and a simple implementation that stores both the config and netflows in uin256.

In the test, we performed a swap with limits only configured on one of the two assets. For this asset, all three limits are configured.

Result:

This Implementation:
check non-configured Limit: 3_453
check configured Limit: 38_203
entire swapIn: 131_890

Uint256 implementation:
check non-configured Limit: 11_091
check configured Limit: 69_217
entire swapIn: 167_091

Conclusion:
Since we are on Celo the gas difference is cheap while the additional calculation logic adds room for error.

@chapati23 chapati23 marked this pull request as draft February 10, 2025 10:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
0