Repository navigation
Scale withdraw, transfer and margin amounts without float truncation - #190
Open
hey-research-lab wants to merge 1 commit into
Open
hey-research-lab wants to merge 1 commit into
hey-research-lab wants to merge 1 commit into
Conversation
int(2.01 * 1e6) is 2009999, so withdraw(USDC, 2.01) signed 2.009999 USDC. Scale through the amount's decimal representation instead.
hey-research-lab
force-pushed
the
fix/exact-amount-scaling
branch
from
October 23, 2026 18:53
d31b936 to
20de90f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
SignerClient.withdraw,transfer,transfer_same_master_account,update_marginandcreate_market_order_quote_amountconvert a human amount to ticks withint(amount * scale). Binary floating point makes many ordinary amounts land just below the integer, so the truncation signs one tick less than asked:withdraw(ASSET_ID_USDC, ..., 2.01)signs 2009999 (2.009999 USDC), andwithdraw(ASSET_ID_ETH, ..., 0.29)signs 28999999 (0.28999999 ETH). Of the two-decimal amounts from 0.01 to 1000.00, 1,196 are affected at the USDC scale (1e6); of those from 0.01 to 100.00, 698 are affected at the 1e8 scale.Why
lighter/signer_client.py(before this change): line 941quote_amount = int(quote_amount * 1e6), lines 1238, 1353 and 1369amount = int(amount * self.ASSET_TO_TICKER_SCALE[asset_id]), and line 1471usdc_amount = int(usdc_amount * self.USDC_TICKER_SCALE).2.01 * 1e6 == 2009999.9999999998and0.29 * 1e8 == 28999999.999999996;int()truncates both down.How
A small
to_ticks(amount, scale)helper scales through the amount's decimal representation (Decimal(str(amount)) * Decimal(scale)) and truncates the result, so2.01becomes exactly 2010000, while precision finer than one tick is still truncated as before (1.0000009USDC stays 1000000). The five call sites use it. No other behaviour changes.Testing
Added
test/test_amount_scaling.py, which callsSignerClient.withdrawwith a stubsign_withdrawand checks the amount it receives.pytest test/test_amount_scaling.py→ 2 failed (USDC 2.01 → 2009999, ETH 0.29 → 28999999), 1 passed.pytest test/→ 4 passed.flake8 . --select=E9,F63,F7,F82(the CI's blocking lint) on the changed files → 0.