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
Python program that generates random user from API

RandomUserPy Author kirito sate #modules used requests, json, tkinter, PIL, urllib, io, install requests and PIL modules from pypi pip install Pillow

kiritosate 1 Jan 05, 2022
Estimate the Market Size for Electic and Plug-In Hybrid Vehicles In Africa

Estimate the Market Size for Electic and Plug-In Hybrid Vehicles In Africa The goal of this repository is to use open data repositories to answer the

Leonce Nshuti 0 Feb 21, 2022
ABT aka Animated Background Tool is a windows only python program that makes it that you can have animated background.

ABT ABT aka Animated Background Tool is a windows only python program that makes it that you can have animated background. 𝓡𝓔𝓐𝓓 𝓜𝓔, An Important

Yeeterboi4 2 Jul 16, 2022
dynamically create __slots__ objects with less code

slots_factory Factory functions and decorators for creating slot objects Slots are a python construct that allows users to create an object that doesn

Michael Green 2 Sep 07, 2021
Utility functions for working with data from Nix in Python

Pynixutil - Utility functions for working with data from Nix in Python Examples Base32 encoding/decoding import pynixutil input = "v5sv61sszx301i0x6x

Tweag 11 Dec 16, 2022
The Official Jaseci Code Repository

Jaseci Release Notes Version 1.2.2 Updates Added new built-ins for nodes and edges (context, info, and details) Fixed dot output Added reset command t

136 Dec 20, 2022
Tiling manager which runs on top of EWMH window managers.

PyTyle is an extremely versatile and extensible tiling manager that is meant to be used on top of EWMH window managers. Its feature set was modeled af

55 Jul 29, 2021
Weakly-Divisable - Takes an interger and seee if it is weakly divisible by seven

Weakly Divisble Project by Diana Arce-Hernandez, Ryan McAlpine, and Rommel Ravan

Diana Arce-Hernandez 1 Jan 12, 2022
Simple Denial of Service Program yang di bikin menggunakan bahasa pemograman Python,

Peringatan Tujuan kami share code Indo-DoS hanya untuk bertujuan edukasi / pembelajaran! Dilarang memperjual belikan source ini / memperjual-belikan s

SonLyte 8 Nov 07, 2021
Make after-work Mending More flexible In Python

Mending Make after-work Mending More flexible In Python A Lite Package focuses on making project's after-post mending pythonic and flexible. Certainly

2 Jun 15, 2022
Discovering local read-level DNA methylation patterns and DNA methylation heterogeneity in intermediately methylated regions

Discovering local read-level DNA methylation patterns and DNA methylation heterogeneity in intermediately methylated regions

1 Jan 11, 2022
This is an online course where you can learn and master the skill of low-level performance analysis and tuning.

Performance Ninja Class This is an online course where you can learn to find and fix low-level performance issues, for example CPU cache misses and br

Denis Bakhvalov 1.2k Dec 30, 2022
YourX: URL Clusterer With Python

YourX | URL Clusterer Screenshots Instructions for running Install requirements

ARPSyndicate 1 Mar 11, 2022
🛠️ Plugin to integrate Chuy with Poetry

Archived This is bundled with Chuy since v1.3.0. Poetry Chuy Plugin This plugin integrates Chuy with Poetry. Note: This only works in Poetry 1.2.0 or

Eliaz Bobadilla 4 Sep 24, 2021
A Desktop application for the signalum python library

Signalum Desktop A Desktop application on the Signalum Python Library/CLI Tool. The Signalum Desktop application is an attempt to develop a single too

BISOHNS 35 Feb 15, 2021
プレヤフHackUチーム「キャット・タン」が作成したアプリ「illustection」

cat_tongue_illustection プレヤフHackUチーム「キャット・タン」が作成した, プライバシー保護アプリ「illustection」です! デモ動画 https://youtu.be/z3I7LuB_i58 機能 アップロードされた画像をいい感じのイラストやの素材に置き換える(

4 Jul 03, 2021
Exploiting Linksys WRT54G using a vulnerability I found.

Exploiting Linksys WRT54G Exploit # Install the requirements. pip install -r requirements.txt ROUTER_HOST=192.169.1.1 ROUTER_USERNAME=admin ROUTER_P

Elon Gliksberg 31 May 29, 2022
Collections of python projects

nppy, mostly contains projects written in Python. Some projects are very simple while some are a bit lenghty and difficult(for beginners) Requirements

ghanteyyy 75 Dec 20, 2022
Transform a Google Drive server into a VFX pipeline ready server

Google Drive VFX Server VFX Pipeline About The Project Quick tutorial to setup a Google Drive Server for multiple machines access, and VFX Pipeline on

Valentin Beaumont 17 Jun 27, 2022
My attempt at this years Advent of Code!

Advent-of-code-2021 My attempt at this years Advent of Code! day 1: ** day 2: ** day 3: ** day 4: ** day 5: ** day 6: ** day 7: ** day 8: * day 9: day

1 Jul 06, 2022