Solidity Libraries – Can Library Functions Work for Non-Storage Structs?

solidity

I'm just getting started with solidity, and I'm working on a contract that calculates the periodic payment on an amortized loan. My goal is to implement the annuity formula:

annuity formula

I've started a library for rational data and a struct for the fraction. In order for the library function to compile the function signature requires any struct parameters be marked with the storage keyword.

library Rational
{
    struct FractionUint
    {
        uint numerator;
        uint denominator;
    }

    function multiply(FractionUint storage self, FractionUint storage other)
    {
        self.numerator *= other.numerator;
        self.denominator *= other.denominator;
    }

...
}

contract testRational
{
    using Rational for Rational.FractionUint;
    Rational.FractionUint f1;
    Rational.FractionUint f2;

    function testMultiply()
    {
        f1 = Rational.FractionUint(1,10);
        f2 = FractionUint(100,2);
        f1.multiply(f2);
        if (f1.numerator != 100)
            throw;
        if (f1.denominator != 20)
            throw;
    }

    /*
    function testMultiply2()
    {
        var f3 = Rational.FractionUint(1,10);
        var f4 = Rational.FractionUint(100,2);
        f3.multiply(f4);
        if (f3.numerator != 100)
        throw;
        if (f3.denominator != 20)
        throw;
    }
    */
}

Compiling testMultiply2 restults in the error:

Error: Member "multiply" is not available in struct FractionUint memory outside of storage.

There are multiple intermediate steps for which I'd like to use some variables defined in the scope of the contract function.

Can a library function called from a contract function perform operations on variables defined in the contract function scope?

Best Answer

Libraries can operate on structs in storage (that's one of their main purposes) but are currently unable to operate on memory structs (lifting this limitation is planned, though).

For your general problem concerning fractional numbers, I would propose different solutions, though:

  1. either combine the two uints into a single uint (256 bits is a lot) or use uint[2] instead of the struct
  2. wait for Solidity to receive fixed point integers (they should come "soon")
Related Topic