Cairo-math-64x61 - Fixed point 64.61 math library for Cairo / Starknet

Overview

Cairo Math 64x61

A fixed point 64.61 math library for Cairo & Starknet

Signed 64.61 Fixed Point Numbers

A signed 64.61-bit fixed point number is a fraction in which the numerator is a signed 125-bit integer and the denominator is 2^61. Since the denominator stays the same there is no need to store it (as in a floating point value).

64.61 is utilized as the 125 bit representation allows for overflow up to 2^125 * 2^125 (250 bits) during calculation taking advantage of Cairo's 251 bit felts.

Can represent values in the range of -2^64 to 2^64 with precision to 4.34e-19.

Standard Library

Math64x61 includes implementation of mul, div, sqrt, exp, ln, log2, log10, and pow as well as conversion and assertion methods.

Trigonometry Library

Trig64x61 includes implementation of sin, cos, tan and their inverses.

Hyperbolic Library

Hyp64x61 includes implementation of sinh, cosh, tanh, and their inverses.

Extensibility

This library strives to adhere to the OpenZeppelin extensibility pattern: https://github.com/OpenZeppelin/cairo-contracts/blob/main/docs/Extensibility.md

Comments
  • dev: add namespaces

    dev: add namespaces

    Hey,

    I was wondering if you'd accept a PR to introduce namespaces to your lib. Using a namespace is the current accepted best practice, it's much easier on the eyes and to work with from a developer experience perspective.

    See the changes to Math64x61Mock.cairo to get the feel for the difference.

    So far, this PR only has changes in the Math module, but if you're ok with it, I can update Hyp, Trig and Vec as well.

    opened by milancermak 2
  • Function to convert oracle prices

    Function to convert oracle prices

    This PR adds functions that help with using different oracles(https://www.stork.network/, https://empiric.network/, etc). These oracles return prices multiplied by 10**18 and converting these prices to the Math64x61 format can sometimes be quite tricky due to errors in overflow etc.

    Functions proposed here address this problem and can convert such prices to the desired Match64x61 format. Tests are provided as well.

    opened by Chepelau 1
  • OZ standards and PyPi update

    OZ standards and PyPi update

    • Updated to adhere to open zeppelin lib extensibility standards (breaking change, requires changing imports / method refs)
    • Switched from npm to pip module installation to better support cairo / python ecosystem
    • removed starknet language declarations to allow for usage in cairo projects (see #3)
    opened by clexmond 0
  • Rounding bug when using library

    Rounding bug when using library

    Hi, we have a precision bug when converting felts with the library and would like to get some help.

    We have a fee rate that we store globally and per account. The value of the fee rate is 0.0004 but before the value is sent to the contract function we add some quantum precision to it by doing (i.e 0.0004 * 10^8) and then send it as 40000. In the function where the fee rate is used, we remove this precision by doing a Math.to_decimal8(feeRate). All Math.to_decimal8(feeRate) does is remove the quantum precision before the fee rate is stored in storage.

    To further illustrate this, when we try to retrieve the fee rate stored, instead of getting 40000, the value returned is 39999. But it does not stop there. We also noticed that when the fee rate is a multiple of 5, the exact value is returned with no change in precision. Eg 0.0005 (or 50000) returns 50000. But any other value that is not a multiple of 5 loses precision.

    A code sample to demonstrate this is attached below.

    // SPDX-License-Identifier: Apache-2.0
    %lang starknet
    
    from cairo_math_64x61.math64x61 import Math64x61
    from starkware.cairo.common.bool import TRUE, FALSE
    from starkware.cairo.common.cairo_builtins import HashBuiltin
    
    struct FeeRate {
        exists: felt,
        maker: felt,
        taker: felt,
    }
    
    @storage_var
    func global_fee_rate() -> (feeRate: FeeRate) {
    }
    
    @storage_var
    func account_fee_rate(account: felt) -> (feeRate: FeeRate) {
    }
    
    namespace Math {
        const DOT8 = (10 ** 8) * Math64x61.FRACT_PART;
        func to_decimal8{range_check_ptr}(num: felt) -> felt {
           alloc_locals;
           // To fixed precision
           local _ans = Math64x61.fromFelt(num);
           // Remove quantum precision
           let ans = Math64x61.div(_ans, DOT8);
           return ans;
        }
    
        func to_felt8{range_check_ptr}(num: felt) -> felt {
            // Add quantum precision
            let _ans =  Math64x61.mul(num, DOT8);
            // Remove fixed precision
            let ans = Math64x61.toFelt(_ans);
            return ans;
        }
    }
    
    @external
    func convertAndSetGlobalFeeRate{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        maker_fee: felt, taker_fee: felt
    ) {
        alloc_locals;
    
        let maker_fee_d = Math.to_decimal8(maker_fee);
        let taker_fee_d = Math.to_decimal8(taker_fee);
    
        let fee_rate_d = FeeRate(exists=1, maker=maker_fee_d, taker=taker_fee_d);
        global_fee_rate.write(fee_rate_d);
    
        return ();
    }
    
    @view
    func convertAndGetAccountFeeRate{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
        account: felt) -> (fee_rate: FeeRate) {
        alloc_locals;
        let (_account_fee_rate) = account_fee_rate.read(account);
    
        if (_account_fee_rate.exists != FALSE) {
            return (_account_fee_rate,);
        }
    
        // Return global fee rate if account fee rate is not set
        let (_global_fee_rate) = global_fee_rate.read();
        let maker_fee = Math.to_felt8(_global_fee_rate.maker);
        let taker_fee = Math.to_felt8(_global_fee_rate.taker);
    
        let fee_rate = FeeRate(
            exists=1,
            maker=maker_fee,
            taker=taker_fee,
        );
        return (fee_rate,);
    }
    
    

    Here's a test case that shows that converting the fee_rate to decimal_8 before storage and after retrieval

    import dataclasses
    import os
    
    import pytest
    from starkware.starknet.testing.starknet import Starknet
    from starkware.starkware_utils.error_handling import StarkException
    
    from .types import TokenAsset
    from .utils import str_to_felt, to_quantum
    
    FILE_DIR = os.path.dirname(__file__)
    CAIRO_PATH = [os.path.join(FILE_DIR, "../contracts")]
    ROUNDING_FILE = os.path.join(FILE_DIR, "../contracts/test/Rounding.cairo")
    ACCOUNT_ADDRESS = str_to_felt("ACCOUNT ADDRESS")
    
    @pytest.fixture()
    async def contracts():
        starknet = await Starknet.empty()
        rounding_contract = await starknet.deploy(
            source=ROUNDING_FILE, cairo_path=CAIRO_PATH, disable_hint_validation=True
        )
    
        return rounding_contract
    
    async def test_fee_rate_with_rounding(contracts):
        rounding_contract = contracts
        maker_fee_rate = to_quantum(0.0001)
        taker_fee_rate = to_quantum(0.0004)
        await rounding_contract.convertAndSetGlobalFeeRate(
            maker_fee_rate,
            taker_fee_rate
        ).execute()
    
        account_fee_rates = await rounding_contract.convertAndGetAccountFeeRate(ACCOUNT_ADDRESS).call()
        assert not (account_fee_rates.result.fee_rate.maker == maker_fee_rate)
        assert not (account_fee_rates.result.fee_rate.taker == taker_fee_rate)
    

    I will be happy to provide further information to help debug this issue. Thanks!

    opened by mayowaparadigm 0
  • A bug in the function`ceil`

    A bug in the function`ceil`

    If the input of the ceil function is an integer x(that is, x modulo FRACT_PART is equal to 0), it will return x+1. But I think this does not match the usual semantics of ceil function in mathematics.

    The bug is found by Medjai, a symbolic execution tool for the Cairo program. The spec we write for ceil is:

    func ceil_spec{range_check_ptr}():
        alloc_locals
        let (local x) = SymbolicMath64x61()
        let (local res) = Math64x61.ceil(x)
        verify_le_signed(x, res)
        verify_lt_signed(res - Math64x61.ONE, x)
        let (_, rem) = signed_div_rem(res, Math64x61.ONE, Math64x61.BOUND)
        medjai_assert_eq_felt(rem, 0)
        return ()
    end
    
    opened by DOFYPXY 0
  • toUint256() function should return the number without the floating part

    toUint256() function should return the number without the floating part

    Thanks to the great lib.

    I just have one remark. I expected the toUint256() function to return the number rounded as Uint256. For example: passing 12,3456 I expect to get 12 from toUint256() To get the right result I have to pass my 12,3456 into the toFelt() function and then the toUint256().

    Also we can add what type of rounding we want as param to the function.

    Best,

    opened by FabienCoutant 0
  • Function for converting oracles

    Function for converting oracles

    Starknet oracles (Empiric network, Stork etc.) provide prices of assets multiplied by 10^18. This can present a challenge when we want to end with price multiplied by 2**61 instead, due to overflow etc. For this reason, I'd like to add a function that manages to convert such prices to the Math64x61 format. Tested to 5e-15 precision.

    opened by Chepelau 0
  • Add 'unsafe' versions of each function

    Add 'unsafe' versions of each function

    Math64x61_assert64x61 is expensive! I was able to reduce the step count of a function by close to 60% just by getting rid of that assert where it wasn't necessary (meaning the fixed-point operations were guaranteed to not overflow).

    Of course these should be used very carefully, but I think they'd be a useful addition.

    opened by bllu404 0
Releases(v2.1.0)
Owner
Influence
A grand strategy game set in an asteroid belt and built on Ethereum.
Influence
navigation_commander is a ROS package to command the robot to navigate autonomously to each table for food delivery inside a hotel.

navigation_commander navigation_commander is a ROS package to command the robot to navigate autonomously to each table for food delivery inside a hote

ALEENA LENTIN 9 Nov 08, 2021
Github dorking tool

gh-dork Supply a list of dorks and, optionally, one of the following: a user (-u) a file with a list of users (-uf) an organization (-org) a file with

Molly White 119 Dec 21, 2022
Opensource Desktop application for kenobi.

Kenobi-Server WIP Opensource desktop application for Kenobi. Download the apple watch app to get started. What is this repo? It's repo for the opensou

Aayush 9 Oct 08, 2022
API Rate Limit Decorator

ratelimit APIs are a very common way to interact with web services. As the need to consume data grows, so does the number of API calls necessary to re

Tomas Basham 574 Dec 26, 2022
Minitel 5 somewhat reverse-engineered

Minitel 5 The Minitel was a french dumb terminal with an embedded modem which had its Golden Age before the rise of Internet. Typically cubic, with an

cLx 10 Dec 28, 2022
Check COVID locations of interest against Google location history

Location of Interest Checker Script to compare COVID locations of interest to Google location history. The script produces a map plot (as shown below)

9 Mar 30, 2022
carrier.py is a Python package/module that's used to save time when programming

carrier.py is a Python package/module that's used to save time when programming, it helps with functions such as 24 and 12 hour time, Discord webhooks, etc

Zacky2613 2 Mar 20, 2022
creates a batch file that uses adb to auto-install apks into the Windows Subsystem for Android and registers it as the default application to open apks.

wsa-apktool creates a batch file that uses adb to auto-install apks into the Windows Subsystem for Android and registers it as the default application

Aditya Vikram 3 Apr 05, 2022
Transform your boring distro into a hacking powerhouse.

Pentizer Transform your boring distro into a hacking powerhouse. Pentizer is a personal project that imports Kali and Parrot repositories in any Debia

Michail Tsimpliarakis 2 Nov 05, 2021
Multi-Process / Censorship Detection

Multi-Process / Censorship Detection

Baris Dincer 2 Dec 22, 2021
Moleey Panel with python 3

Painel-Moleey pkg upgrade && pkg update pkg install python3 pip install pyfiglet pip install colored pip install requests pip install phonenumbers pkg

Moleey. 1 Oct 17, 2021
Custom Python code for calculating the Probability of Profit (POP) for options trading strategies using Monte Carlo Simulations.

Custom Python code for calculating the Probability of Profit (POP) for options trading strategies using Monte Carlo Simulations.

35 Nov 22, 2022
Repository specifically for tcss503-22-wi Students

TCSS503: Algorithms and Problem Solving for Software Developers Course Description Introduces advanced data structures and key algorithmic techniques

Kevin E. Anderson 3 Nov 08, 2022
Camera track the tip of a pen to use as a drawing tablet

cablet Camera track the tip of a pen to use as a drawing tablet Setup You will need: Writing utensil with a colored tip (preferably blue or green) Bac

14 Feb 20, 2022
Submission to the HEAR2021 Challenge

Submission to the HEAR 2021 Challenge For model evaluation, python=3.8 and cuda10.2 with cudnn7.6.5 have been tested. The work uses a mixed supervised

Heinrich Dinkel 10 Dec 08, 2022
A fast Python in-process signal/event dispatching system.

Blinker Blinker provides a fast dispatching system that allows any number of interested parties to subscribe to events, or "signals". Signal receivers

jason kirtland 1.4k Dec 31, 2022
Covid-ChatBot - A Rapid Response Virtual Agent for Covid-19 Queries

COVID-19 CHatBot A Rapid Response Virtual Agent for Covid-19 Queries Contents What is ChatBot Types of ChatBots About the Project Dataset Prerequisite

NelakurthiSudheer 2 Jan 04, 2022
Acesse seus investimentos da NuInvest pelo Python (Experimental)

Acesse seus investimentos da NuInvest pelo Python (Experimental)

André Roggeri Campos 5 Dec 06, 2022
Rotazioni: a linear programming workout split optimizer

Rotazioni: a linear programming workout split optimizer Dependencies Dependencies for the frontend and backend are respectively listed in client/packa

Marco 3 Oct 13, 2022
Karte der Allgemeinverfügungen zu Schulschließungen oder eingeschränktem Regelbetrieb in Sachsen

SNSZ Karte Datenquelle: Allgemeinverfügungen zu Schulschließungen oder eingeschränktem Regelbetrieb in Sachsen Sächsisches Staatsministerium für Kultu

Jannis Leidel 3 Sep 26, 2022