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
This repository is an archive of emails that are sent by the awesome Quincy Larson every week.

Awesome Quincy Larson Email Archive This repository is an archive of emails that are sent by the awesome Quincy Larson every week. If you fi

Sourabh Joshi 912 Jan 05, 2023
Simple calculator made in python

calculator Uma alculadora simples feita em python CMD, PowerShell, Bash ✔️ Início 💻 apt-get update apt-get upgrade -y apt-get install python git git

Spyware 8 Dec 28, 2021
Oregon State University grade distributions from Fall 2018 through Summer 2021

Oregon State University Grades Oregon State University grade distributions from Fall 2018 through Summer 2021 obtained through a Freedom Of Informatio

Melanie Gutzmann 5 May 02, 2022
Covid-ml-predictors - COVID predictions using AI.

COVID Predictions This repo contains ML models to be trained on COVID-19 data from the UK, sourced off of Kaggle here. This uses many different ML mod

1 Jan 09, 2022
MoBioTools A simple yet versatile toolkit to automatically setup quantum mechanics/molecular mechanics

A simple yet versatile toolkit to setup quantum mechanical/molecular mechanical (QM/MM) calculations from molecular dynamics trajectories.

MoBioChem 17 Nov 27, 2022
An open-source Python project series where beginners can contribute and practice coding.

Python Mini Projects A collection of easy Python small projects to help you improve your programming skills. Table Of Contents Aim Of The Project Cont

Leah Nguyen 491 Jan 04, 2023
Kunai Shitty Raider Leaked LMFAO

Kunai-Raider-Leaked Kunai Shitty Raider Leaked LMFA

5 Nov 24, 2021
Active Transport Analytics Model: A new strategic transport modelling and data visualization framework

{ATAM} Active Transport Analytics Model Active Transport Analytics Model (“ATAM”

ATAM Analytics 2 Dec 21, 2022
Wannier & vASP Postprocessing module

WASPP module Wannier90 & vASP Postprocessing module with functionalities I needed during my PhD. Being updated Version: 0.5 Main functions: Wannier90

Irián Sánchez Ramírez 4 Dec 27, 2022
The best free and open-source automated time tracker. Cross-platform, extensible, privacy-focused.

Records what you do so that you can know how you've spent your time. All in a secure way where you control the data. Website — Forum — Documentation —

ActivityWatch 7.8k Jan 09, 2023
An example of Connecting a MySQL Database with Python Code

An example of Connecting a MySQL Database with Python Code And How to install Table of contents General info Technologies Setup General info In this p

Mohammad Hosseinzadeh 1 Nov 23, 2021
A simple package for interacting with the 9kw.eu anti-captcha service.

Welcome to captcha9kw’s documentation! captcha9kw is a smallish Python package for making use of the 9kw.eu services, including solving of interactive

2 Feb 26, 2022
Multi-Probe Attention for Semantic Indexing

Multi-Probe Attention for Semantic Indexing About This project is developed for the topic of COVID-19 semantic indexing. Directories & files A. The di

Jinghang Gu 1 Dec 18, 2022
Скрипт позволяет выгрузить участников чатов/каналов(по чату для комментариев) и сообщения в различные форматы файлов.

TG-Parser Парсер участников и сообщений из ТГ-Чатов и чатов для комментариев в ТГ-Каналах Возможности Выгрузка участников групп/каналов(по чату для ко

50 Jan 06, 2023
📙 Super lightweight function registries for your library

catalogue: Super lightweight function registries for your library catalogue is a tiny, zero-dependencies library that makes it easy to add function (o

Explosion 139 Jan 02, 2023
A Python application that helps users determine their calorie intake, and automatically generates customized weekly meal and workout plans based on metrics computed using their physical parameters

A Python application that helps users determine their calorie intake, and automatically generates customized weekly meal and workout plans based on metrics computed using their physical parameters

Anam Iqbal 1 Jan 13, 2022
Hypothesis strategies for generating Python programs, something like CSmith

hypothesmith Hypothesis strategies for generating Python programs, something like CSmith. This is definitely pre-alpha, but if you want to play with i

Zac Hatfield-Dodds 73 Dec 14, 2022
Python script to autodetect a base set of swiftlint rules.

swiftlint-autodetect Python script to autodetect a base set of swiftlint rules. Installation brew install pipx

Jonathan Wight 24 Sep 20, 2022
Absolute solvation free energy calculations with OpenFF and OpenMM

ABsolute SOLVantion Free Energy Calculations The absolv framework aims to offer a simple API for computing the change in free energy when transferring

7 Dec 07, 2022
This is a spamming selfbot that has custom spammed message and @everyone spam.

This is a spamming selfbot that has custom spammed message and @everyone spam.

astro1212 1 Jul 31, 2022