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
ChieriBot,词云API版,用于统计群友说过的怪话

wordCloud_API 词云API版,用于统计群友说过的怪话,基于wordCloud 消息储存在mysql数据库中.数据表结构见table.sql 为啥要做成API:这玩意太吃性能了,如果和Bot放在同一个服务器,可能会影响到bot的正常运行 你服务器性能够用的话就当我在放屁 依赖包 pip i

chinosk 7 Mar 20, 2022
Python - Aprendendo Python na ByLearn

PYTHON Identação Escopo Pai Escopo filho Escopo neto Variaveis

Italo Rafael 3 May 31, 2022
Runtime fault injection platform by Daniele Rizzieri (2021)

GDBitflip [v1.04] Runtime fault injection platform by Daniele Rizzieri (2021) This platform executes N times a binary and during each execution it inj

Daniele Rizzieri 1 Dec 07, 2021
Read and write life sciences file formats

Python-bioformats is a Python wrapper for Bio-Formats, a standalone Java library for reading and writing life sciences image file formats. Bio-Formats

CellProfiler 106 Dec 19, 2022
Implementation of the MDMC method to search for magnetic ground state using VASP

Implementation of MDMC method ( by Olga Vekilova ) to search for magnetic ground state using VASP

Utkarsh Singh 1 Nov 27, 2021
Used the pyautogui library to automate some processes on the computer

Pyautogui Utilizei a biblioteca pyautogui para automatizar alguns processos no c

Dheovani Xavier 1 Dec 30, 2021
This script can be used to get unlimited Gb for WARP.

Warp-Unlimited-GB This script can be used to get unlimited Gb for WARP. How to use Change the value of the 'referrer' to warp id of yours You can down

Anix Sam Saji 1 Feb 14, 2022
CaskDB is a disk-based, embedded, persistent, key-value store based on the Riak's bitcask paper, written in Python.

CaskDB - Disk based Log Structured Hash Table Store CaskDB is a disk-based, embedded, persistent, key-value store based on the Riak's bitcask paper, w

886 Dec 27, 2022
Our product DrLeaf which not only makes the work easier but also reduces the effort and expenditure of the farmer to identify the disease and its treatment methods.

Our product DrLeaf which not only makes the work easier but also reduces the effort and expenditure of the farmer to identify the disease and its treatment methods. We have to upload the image of an

Aniruddha Jana 2 Feb 02, 2022
Apache Superset out of box version(Windows 64-bit)

superset_app Apache Superset out of box version (Windows 64bit) prepare job download 3 files python-3.8.10-embed-amd64.zip get-pip.py python_geohash‑0

Steven Lee 9 Oct 02, 2022
A data engineering project with Kafka, Spark Streaming, dbt, Docker, Airflow, Terraform, GCP and much more!

Streamify A data pipeline with Kafka, Spark Streaming, dbt, Docker, Airflow, Terraform, GCP and much more! Description Objective The project will stre

Ankur Chavda 206 Dec 30, 2022
Open-source data observability for modern data teams

Use cases Monitor your data warehouse in minutes: Data anomalies monitoring as dbt tests Data lineage made simple, reliable, and automated dbt operati

889 Jan 01, 2023
The repository is about 100+ python programming exercise problem discussed, explained, and solved in different ways

Break The Ice With Python A journey of 100+ simple yet interesting problems which are explained, solved, discussed in different pythonic ways Introduc

Abdullah Al Masud Tushar 2.2k Jan 04, 2023
Collection of Beginner to Intermediate level Python scripts contributed by members and participants.

Hacktoberfest2021-Python Hello there! This repository contains a 'Collection of Beginner to Intermediate level Python projects', created specially for

12 May 25, 2022
Experimental proxy for dumping the unencrypted packet data from Brawl Stars (WIP)

Brawl Stars Proxy Experimental proxy for version 39.99 of Brawl Stars. It allows you to capture the packets being sent between the Brawl Stars client

4 Oct 29, 2021
Resources for the 2021 offering of COMP 598

comp598-2021 Resources for the 2021 offering of COMP 598 General submission instructions Important Please read these instructions located in the corre

Derek Ruths 23 May 18, 2022
Odoo. Open Source Apps To Grow Your Business.

Odoo Odoo is a suite of web based open source business apps. The main Odoo Apps include an Open Source CRM, Website Builder, eCommerce, Warehouse Mana

Odoo 27.6k Jan 09, 2023
Ingest openldap data into bloodhound

Bloodhound for Linux Ingest a dumped OpenLDAP ldif into neo4j to be visualized in Bloodhound. Usage: ./ldif_to_neo4j.py ./sample.ldif | cypher-shell -

Guillaume Quéré 71 Nov 09, 2022
A jokes python module

Made with Python3 (C) @FayasNoushad Copyright permission under MIT License License - https://github.com/FayasNoushad/Jokes/blob/main/LICENSE Deploy

Fayas Noushad 3 Nov 28, 2021
🚀 emojimash 🚀 is a programming language with ALL THE EMOJI

🚀 emojimash 🚀 is a programming language with ALL THE EMOJI

Python Whiz 256 1 Oct 26, 2021