Improving the Ethereum Developer Ecosystem with Libraries
The Ethereum development ecosystem is lacking many tools which we take for granted in other programming environments. That’s why we’ve been working on our cryptofin-solidity library.
A good library lets developers write less code which reduces bugs and saves development time. For blockchain development, libraries are even more impactful because they:
- save gas for end users if they’re optimized
- reduce the amount of code that needs to be audited
We’ve collected various methods in our cryptofin-solidity repo, with an initial focus on array utilities.
We’ll show you how to set it up in less than 10 seconds, then dive into some interesting code that’ll make you feel like you’ve done something productive today!
Quickstart
npm install --save cryptofin-solidity
Use it in a project
Assuming you’re using Truffle or something similar:
import "cryptofin-solidity/contracts/array-utils/AddressArrayUtils.sol";contract Contract {
using AddressArrayUtils for address[]; function containsDeadBeef(address[] memory addresses)
returns (bool)
{
return addresses.contains(address(0xdeadbeef));
}}
And that’s it!
For more examples and documentation, see the GitHub.
Into the weeds
Let’s look at some cool and useful functionality.
indexOf
and contains
indexOf
gives the first index of an element in an array. It returns (uint256, bool)
which allows us to implement contains
in just two lines using multiple assignment:
(, bool isIn) = indexOf(A, a); // Ignore uint256 index
return isIn;
map, reduce, filter
These are cool because they use a relatively unknown feature of Solidity: functional programming!
reduce
and filter
follow similar patterns.
Example:
uint256[] memory nonZeros = array.filter(isNonZero);
union
Using other library functions included in cryptofin-solidity (difference
, intersect
, and extend
), we can very easily compute the union of two sets.
Recall that the union of two sets is:
{A - B} + {A ^ B} + {B - A}
sPopCheap
Let’s break it down:
s
: signifies that this operates on a storage array rather than a memory array (the default)pop
: removes the element at the givenindex
and returns that elementcheap
: The usual way to implement pop is to delete the element atindex
and shift all subsequent elements to the left. The gas costs scale O(n), so an alternate algorithm is used to achieve O(1): swap the element atindex
with the last element, then delete the last element.
sPopCheap
doesn’t preserve the array order, and is meant to be used with unordered lists. Another function, sPop
preserves order but is more expensive.
We chose to keep the more expensive version as sPop
because it behaves as expected for new developers.
argFilter and argGet
argFilter
returns the indices that would filter an array, and is inspired by numpy’s argsort. argGet
is like numpy’s indexing of arrays notation.
It allows us to work with data with the following structure:
uint256[] ids: [0, 1, 2, 3, 4]uint256[] ages: [20, 35, 14, 24, 48]address[] addresses: [
0x403B5178d38Cf0520F29592c1536061Ef59ff0BD,
0xF206af3D25f9Fa27b8E68bbA7E6Da953707663D2,
0xa1949d9c2fd3B13A47B04Ae05353C0A3A7573Eb8,
0xf163A8D25BF8c09a9Df4e376A50538FeD301e18c,
0xB5172c7E6B545Fa9Bdd1adCA46fb4e03150C6b0e
]
Let’s say we want to filter out anyone under the age of 21.
function noYoungins(uint256 a) pure returns (bool) {
return a >= 21;
}
Then,
uint256[] memory indexArray = ages.argFilter(noYoungins);filteredIDs = ids.argGet(indexArray);
filteredAges = ages.argGet(indexArray);
filteredAddresses = addresses.argGet(indexArray);
Next Steps
We’d love it if you contributed any general code you’ve written that’s suitable for a library! We’ve met some great developers at events like ETHGlobal, so we know you’re out there reading this!
In the near future, we’ll be tackling the following (and would appreciate some help):
- More functionality
- More tests
- Documentation
- Gas analysis
- Gas optimization
- Auto-generated libraries for different types (
uint128
,uint64
, etc.)
We hope this library is useful for your next Solidity project!
Thanks to Nemil Dalal, Mert Çelebi, Graham Kaemmer, and Liam Horne for feedback on drafts!
CryptoFin designed Bskt, a way to create decentralized ERC20 token portfolios. Join our Telegram group for updates.