-
Notifications
You must be signed in to change notification settings - Fork 595
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimize gas for _getFraction in AmountDeriver #384
Changes from 7 commits
4d5c1f0
0410f66
dea98a6
341d9e4
6d99451
4cd8c9e
4ae3e3e
a2c1d58
5a8575d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,8 @@ import { | |
AmountDerivationErrors | ||
} from "../interfaces/AmountDerivationErrors.sol"; | ||
|
||
import "./AmountDeriverConstants.sol"; | ||
|
||
/** | ||
* @title AmountDeriver | ||
* @author 0age | ||
|
@@ -98,16 +100,14 @@ contract AmountDeriver is AmountDerivationErrors { | |
|
||
// Ensure fraction can be applied to the value with no remainder. Note | ||
// that the denominator cannot be zero. | ||
bool exact; | ||
assembly { | ||
// Ensure new value contains no remainder via mulmod operator. | ||
// Credit to @hrkrshnn + @axic for proposing this optimal solution. | ||
exact := iszero(mulmod(value, numerator, denominator)) | ||
} | ||
|
||
// Ensure that division gave a final result with no remainder. | ||
if (!exact) { | ||
revert InexactFraction(); | ||
// Further optimization by @Chomtana and @0age | ||
if mulmod(value, numerator, denominator) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you sure this does anything? The double There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I mean if the change does anything gas wise. The double iszero should be removed by the optimiser. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It does by removing unnecessary exact variable. exact := iszero(mulmod(value, numerator, denominator)) Don't sure whether optimiser can remove double iszero that is stored into intermediate variable first. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are many optimiser stages, including one which operates on opcode level, where known stack movement are supported. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have just tested gas on remix using 2 separate contracts with same function name getFraction for both case and adding
Normal case (2, 5, 10) Revert case (2, 5, 8) |
||
mstore(0, InexactFraction_error_signature) | ||
revert(0, InexactFraction_error_len) | ||
} | ||
} | ||
|
||
// Multiply the numerator by the value and ensure no overflow occurs. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity >=0.8.7; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why use 0.8.7 here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is copied from ConsiderationConstants.sol let ask @0age should we change to >=0.8.13 or are there any specific cases? In my opinion, it should be >=0.8.13. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
/* | ||
* -------------------------- Disambiguation & Other Notes --------------------- | ||
* - The term "head" is used as it is in the documentation for ABI encoding, | ||
* but only in reference to dynamic types, i.e. it always refers to the | ||
* offset or pointer to the body of a dynamic type. In calldata, the head | ||
* is always an offset (relative to the parent object), while in memory, | ||
* the head is always the pointer to the body. More information found here: | ||
* https://docs.soliditylang.org/en/v0.8.14/abi-spec.html#argument-encoding | ||
* - Note that the length of an array is separate from and precedes the | ||
* head of the array. | ||
* | ||
* - The term "body" is used in place of the term "head" used in the ABI | ||
* documentation. It refers to the start of the data for a dynamic type, | ||
* e.g. the first word of a struct or the first word of the first element | ||
* in an array. | ||
* | ||
* - The term "pointer" is used to describe the absolute position of a value | ||
* and never an offset relative to another value. | ||
* - The suffix "_ptr" refers to a memory pointer. | ||
* - The suffix "_cdPtr" refers to a calldata pointer. | ||
* | ||
* - The term "offset" is used to describe the position of a value relative | ||
* to some parent value. For example, OrderParameters_conduit_offset is the | ||
* offset to the "conduit" value in the OrderParameters struct relative to | ||
* the start of the body. | ||
* - Note: Offsets are used to derive pointers. | ||
* | ||
* - Some structs have pointers defined for all of their fields in this file. | ||
* Lines which are commented out are fields that are not used in the | ||
* codebase but have been left in for readability. | ||
*/ | ||
|
||
// Declare constant for errors related to amount derivation. | ||
|
||
// error InexactFraction() @ AmountDerivationErrors.sol | ||
uint256 constant InexactFraction_error_signature = ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think these should have the error signature as a comment, i.e. Also a reference to the definition There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. More comments has been added |
||
0xc63cf08900000000000000000000000000000000000000000000000000000000 | ||
); | ||
uint256 constant InexactFraction_error_len = 0x20; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can remove the credit here :)