Solidity

Solidity Using For

Solidity Using For Main Tips

  • In Solidity the using A for B directive is used for attaching library functions from one library to another.
  • Using A for * is used to attach the library A‘s functions to any type.

Solidity Using For

In Solidity the using A for B directive is used for attaching library functions from one library (A) to another (B). The attached functions are, in this case, going to receive the object they are called on in the form of their first parameter, much like the variable self in Python.

Using A for * is used to attach the library A‘s functions to any type.

Either way, every single function, including those in which the first parameter’s type would not match the object’s type, is attached. As the function is called, the type is checked, in addition to performing function overload resolution.

The directive of using A for B is active in the current scope, that is limited to a contract currently but is going to become accessible to the global scope further down the line, so when a module is included, the data types that belong to it, which includes library functions, can be accessed without any further code being added.

Let’s rewrite the library example like this:

Example

// Same code as before, only no comments

pragma solidity ^0.4.11;

library SetLib {
  struct LibData { mapping(uint => bool) flagsMapping; }

  function insertData(LibData storage selfStore, uint value)
      returns (bool)
  {
      if (selfStore.flagsMapping[value])
          return false;
      selfStore.flagsMapping[value] = true;
      return true;
  }

  function removeData(LibData storage selfStore, uint value)
      returns (bool)
        {
      if (!selfStore.flagsMapping[value])
          return false;
      selfStore.flagsMapping[value] = false;
      return true;
  }

  function contains(LibData storage selfStore, uint value)
      returns (bool)
  {
      return selfStore.flagsMapping[value];
  }
}

contract Cont {
    SetLib.LibData valuesKnown;

    function registerData(uint value) {
        // Here, all variables of type Set.Data have
        // corresponding member functions.
        // The following function call is identical to
        // Set.insert(knownValues, value)
        require(SetLib.insertData(valuesKnown, value));
    }
}

 

Try on Remix Try live on Hosting

Additionally, this way we can expand elementary types:

Example

pragma solidity ^0.4.0;

library SearchLib {
    function getIndexOf(uint[] storage selfStore, uint value) returns (uint) {
        for (uint n = 0; n < selfStore.length; n++)
            if (selfStore[n] == value) return n;
        return uint(-1);
    }
}

contract Cont {
    using SearchLib for uint[];
    uint[] libData;

    function append(uint value) {
        libData.push(value);
    }

    function replace(uint _oldData, uint _newData) {
        // Will perform library function call
        uint index = libData.getIndexOf(_oldData);
        if (index == uint(-1))
            libData.push(_newData);
        else
            libData[index] = _newData;
    }
}

 

Try on Remix Try live on Hosting

Note: Every library call is an EVM function call, meaning that if memory or value types are passed, a copy is going to be performed, not excluding that of the self variable. Storage reference variable are only used when it is certain that no copy is going to be performed.

Read previous post:
Solidity Libraries

Solidity Libraries Main Tips Libraries in Solidity are similar to contracts, but their purpose is that they are meant to get deployed...

Close