Optimize multiplication check as recent openzeppelin safemath implementation.
One of the things I like Vyper is that it supports safemath from the language.
Its logic is on expr.py.
However, I found a typo in the comment:
from
# Checks that: a == 0 || a / b == b
to
# Checks that: a == 0 || c(which is a*b) / a == b
and a space for gas optimization which was approved in Openzeppelin's SafeMath implementation.
If this change is not approved, comment typo is not fixed and vyper uses more gas than solidity with safemath contract.
Here is the difference of Opcode to be pushed to LLL parse tree:
assert(a==0 || (a*b / a) == b)
['assert', ['or', ['iszero', left],
['eq', ['div', ['mul', left, right], left], right]]],
['mul', left, right]
if (a == 0) { return 0; } // Without verifying a*b / a == b
assert(a*b/a==b);
[ 'if',
['eq', left, 0],
[0],
['seq',
['assert', ['eq', ['div', ['mul', left, right], left], right]],
['mul', left, right]
]
]
Reasons and verification is described on the link here
This version is compatible with the others but it uses less gas for an arithmetic operation.
Copyright and related rights waived via CC0
Wow good catch picking that up from SafeMath! :smile:
I'm missing something about this comment in context of the code. How does checking if and only if a == 0 in order to proceed with any multiplication help?
Oops. I passed out 3 hours ago and checked this. I will implement it right.
@fubuloubu so basically you save gas because you immediately return 0 for 0/x instead of doing all the checks and the mul and return 0 anyways.
Okay, that makes way more sense now lol
Most helpful comment
@fubuloubu so basically you save gas because you immediately return 0 for
0/xinstead of doing all the checks and the mul and return 0 anyways.