-
Notifications
You must be signed in to change notification settings - Fork 103
GeneralIndexModule internal review and external audit revisions #75
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
Conversation
What are the benefits of storing the exchange name as a hash? To me this hurts readability. |
So with Berlin would we expect the gas increase to be slightly less? (I'm assuming this wasn't run with Berlin changes) |
Agree, it's not as nice. There's a note in the review about the cost of storing them as a string.
|
@bweick Yes, the gas report was run on a Berlin EVM. In Istanbul I'd expect these changes to increase costs a lot, but with Berlin they're more expensive but...by a smaller margin. |
Gotcha, that makes sense, though am I reading the table right that the cost of setting exchanges went up? |
@bweick Yes, it went up quite a bit, but it's also validating the exchange name now. From the internal review for
This is a redundant check b/c the trade methods also check. But maybe makes sense from a UX perspective? In practice how frequently are the settings changed? |
I like the check here, if we could remove the check on the trade that'd be great since that is redundant but I think our inherited helper functions there enforce a check? Maybe we can discuss a bit as a group but the readability is really nice. Do we know what the marginal cost of storing a string vs bytes32 is? I know it's going to be different based on string length but would be great to isolate the "cost of readability". |
Changing back to string increases the costs for With a single exchange name longer than 32bytes There was no impact on the trade methods. In the end this is just a few dollars for sets with a small number of components...if exchanges aren't configured very often idk that these gas differences matter that much. |
Do you know if this is possible? I was thinking that validating the adapter is necessary in trade because it could have been removed at some point between setting the exchanges and calling trade. |
Well the only way it could be removed is through setExchanges, in which case a valid exchange would need to be passed in its place. Unless there's a path to removal I'm not thinking of? Also usually we update maybe an exchange or two each time. Obviously if we're adding new components that also requires setting an exchange. |
Can the adapter be removed via the IntegrationRegistry contract? I wrote a test for this possibility in #trade but maybe it's not right... set-protocol-v2/test/protocol/modules/generalIndexModule.spec.ts Lines 910 to 927 in 6f96431
|
Ah yes it could that's a good catch. Then yes I'd say we should check it, even though it would revert if the adapter was invalid it'd be good to return a message. |
address[] calldata _components, | ||
uint256[] calldata _tradeMaximums | ||
address[] memory _components, | ||
uint256[] memory _tradeMaximums |
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.
This change from calldata
to memory
(in four methods) is due to migrating the array pair validators to AddressArrayUtils. There are compiler errors for both permutations of calldata/memory
- preserving
calldata
in this file and making the method signatures at lib and mockscalldata
results in solc erroring with ... (this is a solc bug, according to the error type)
Using solcjs
Compiling 118 files with 0.6.10
InternalCompilerError: Invalid conversion to calldata type.
Error HH600: Compilation failed
- Keeping
calldata
signatures here andmemory
signatures there has solc error with:
Using solcjs
Compiling 118 files with 0.6.10
UnimplementedFeatureError: Copying nested dynamic calldata arrays to memory is not implemented in the old code generator.
Error HH600: Compilation failed
function approximatelyEquals(uint256 a, uint256 b, uint256 range) internal pure returns (bool) { | ||
return a <= b.add(range) && a >= b.sub(range); | ||
} |
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.
Note: this returns true if vals are equal up to and including +/- range (preserving the logic at _targetUnmet)
6a7a7c0
to
1ff05b5
Compare
if (_status) { | ||
permissionInfo[_setToken].tradersHistory.push(_trader); | ||
} else if(permissionInfo[_setToken].tradersHistory.contains(_trader)) { | ||
permissionInfo[_setToken].tradersHistory = permissionInfo[_setToken].tradersHistory.remove(_trader); |
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.
We have a method in AddressArrayUtils
that's way cheaper called removeStorage
, better than having to read it into memory, manipulate, and store.
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.
@@ -2187,6 +2187,24 @@ describe("GeneralIndexModule", () => { | |||
); | |||
}); | |||
|
|||
describe("when de-authorizing a trader", async () => { |
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.
Probably worth checking that the trader history array is updated properly as well
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.
The tradersHistory
is not available on the automatic getter generated by solidity. This is the permissionInfo abi.
{
"inputs": [
{
"internalType": "contract ISetToken",
"name": "",
"type": "address"
}
],
"name": "permissionInfo",
"outputs": [
{
"internalType": "bool",
"name": "anyoneTrade",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function",
"gas": "0x81b320"
},
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.
Only thing we can read out of that without writing a getter is anyoneTrade
. Should we write one?
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.
* Make all revert reason strings < 32bytes * Remove _normalizedTargetMethod getter * Encapsulate _noTokensToSell#canSell logic as internal method * Encapsulate _allTargetsMet#targetUnmet logic in internal method * Validate exchange adapter when setting & store name as bytes32 hash * Consolidate position state and timestamp updates * Validate params for external view methods * Make all external setter method names use prefix `set` * Add RebalanceStarted event * Remove _caller param from onlyAllowedTrader modifier * Add getDefaultPositionRealUnit getter * Encapsulate data aggregation logic in #startRebalance in own method * Prohibit external positions for components in #initialize and #startRebalance * Refactor #createTradeInfo methods * Make weth state variable immutable * Delegate modifier logic to internal helpers in ModuleBase and GeneralIndexModule * Delete trader permissions on module removal / add removeModule tests * Add #validatePairsWithArray methods to AddressArrayUtils library and use in setter methods * Add approximatelyEquals helper in PreciseUnitMath and use in #_targetUnmet * Add AssetTargetsRaised event in RaiseAssetTargets with positionMultiplier arg * Remove trader from permissionInfo.tradersHistory when they are de-authorized * Add getAllowedTraders method and make tradersHistory contain unique elements
Inject gas setting into ABIs and move tasks from hardhat.config to tasks/ (#50) * Inject gas limit into abi on compilation * Move solc & typechain tasks from hardhat.config to tasks/ Add AaveGovernanceV2Adapter (#14) * add basic structure for SnapshotDelegationModule * add delegate function * add SnapshotGovernanceAdapter * code review changes * add aave v2 governance contracts to aave fixture * add AaveGovernanceV2Adapter * add tests for getting proper calldata * add integration test for aave governance v2 adapter * style fixes * code review changes Add CompoundBravoGovernanceAdapter (#17) * add GovernorBravo to compoundFixture * add CompoundBravoGovernanceAdapter * add CompoundBravoGovernanceAdapter tests and fix new gov deploys/fixture * add integration tests for CompoundBravoGovernanceAdapter * code review changes Fix AaveTokenV2Mintable type imports in utils/fixtures Add batch fetch balances and allowances to protocol viewer Remove aliases from import paths in utils/fixtures Bump package version to 0.0.29 Update build and coverage badges for repo rename Move libraryUtils to test folder Fix image tags in build badges for repo renaming Require fully qualified contract name params for library link util Move libraryUtils back to utils/common Bump new version Fix bug in SingleIndexModule's tradeRemainingWETH test (#65) Add CompoundWrapAdapter (#55) Add CompoundWrapAdapter Co-authored-by: mario <[email protected]> port ctoken oracle (#57) Port CToken Oracle Fix failing CompoundWrap tests (#66) Move getRandomAddress (w/out hardhat) to utils/common (#63) Add GeneralIndexModule contract (#59) Add GeneralIndexModule contract, UniswapV2ExchangeAdapterV2 updates, and BalancerV1ExchangeAdapter Co-authored-by: bweick <[email protected]> Remove UniswapYieldStrategy and tests. (#68) Remove UniswapYieldStrategy and tests Add yearn vault wrapper module and oracle (#61) Add Yearn vaults wrap adapter and oracle for valuing yTokens. Co-authored-by: bweick <[email protected]> Organize integrations folder into integration type. (#70) Updated javadocs for GeneralIndexModule. (#71) Updated javadocs for GeneralIndexModule. Bumped package. (#73) Remove trailing whitespace in GeneralIndexModule.sol Specify gas and blockGasLimit for localhost network Add new Uniswap transfer fee adapter Bump to 0.0.33 Add BalancerV1ExchangeAdapter tests (#72) * Add balancerV1ExchangeAdapter tests * Refactor uniswapV2ExchangeAdapter and add getDataParam test * Re-add deleted functions in deployAdapter.ts GeneralIndexModule internal review and external audit revisions (#75) * Make all revert reason strings < 32bytes * Remove _normalizedTargetMethod getter * Encapsulate _noTokensToSell#canSell logic as internal method * Encapsulate _allTargetsMet#targetUnmet logic in internal method * Validate exchange adapter when setting & store name as bytes32 hash * Consolidate position state and timestamp updates * Validate params for external view methods * Make all external setter method names use prefix `set` * Add RebalanceStarted event * Remove _caller param from onlyAllowedTrader modifier * Add getDefaultPositionRealUnit getter * Encapsulate data aggregation logic in #startRebalance in own method * Prohibit external positions for components in #initialize and #startRebalance * Refactor #createTradeInfo methods * Make weth state variable immutable * Delegate modifier logic to internal helpers in ModuleBase and GeneralIndexModule * Delete trader permissions on module removal / add removeModule tests * Add #validatePairsWithArray methods to AddressArrayUtils library and use in setter methods * Add approximatelyEquals helper in PreciseUnitMath and use in #_targetUnmet * Add AssetTargetsRaised event in RaiseAssetTargets with positionMultiplier arg * Remove trader from permissionInfo.tradersHistory when they are de-authorized * Add getAllowedTraders method and make tradersHistory contain unique elements Added an exchangeData param on the GIM (#76) Added an exchangeData param on the GIM. Allows passing in arbitrary parameter or execution info to an exchange. Made all GIM adapters specific to GIM and not compatible with TradeModule. restructure test/protocol/integration into folders (#79) Final review fixes for GeneralIndexModule (#83) * Add math boundary cases for protocol fee and raise target percentage * Add external position modules check to #_validateTradeParameters * Group internal methods by function and importance * Remove TargetUnitsUpdated event, update RebalanceStarted event * Add explanatory note about fixed / floating limit * 0.0.35 Upgrade hardhat to 2.2.1 (Berlin) / add test:fast yarn commands (#78) * Upgrade hardhat to 2.2.1 (Berlin) / add test:fast yarn commands * Increase Yearn external abi gas estimates by 1 order of magnitude KNC Migration Adapter (#86) * Add Kyber migration adapter contract * Add tests * Add @openzeppelin/[email protected] as dependency * Add external contract KyberNetworkTokenV2 * Updated KyberNetworkTokenV2 abi * Add missing test and remove proxy from contract * Remove external dependency openzeppelin/contracts-upgradeable * Fix variable names and bump package Add AXS migration wrap adapter (#87) * Add Axie Infinity migration wrap adapter contract * Add external TokenSwap contract * Add tests for axie infinity migration wrap adapter * Modify adapter to serve as middleware contract for migration * Fix bugs and add tests * Fixed external TokenSwap contract bytecode * Explain migration process in javadocs * Bump package to 0.0.37 Adding StandardTokenMock#mint Adding CompClaimAdapter feat: initial stab at Uniswap V3 adaptor feat: verify uniswap path for single hops WIP feat: verify path for multiple hops fix: add proper tests, require statements for sellTokenForToken refactor: move decoding tokens from encoded path into reusable function feat: implement sellTokenForEthToUniswapV3 and sellEthForTokenToUniswapV3 fix: address review feedback fix: sellEthForTokenToUniswapV3 impl and address review comments refactor: clean up Uniswap V3 path decoding logic fix: remove incorrect require check for sellEthForTokenToUniswapV3 Update package for public npm (make ethers a non-dev dep) (#92) ZeroExAdapter null recipient fix (#93) 0.0.38 (#94) Add Uniswap V3 Fixture (#95) * add basic Uniswap V3 fixture * add createPool to fixture * add quoter * add getTokenOrder helper * add addLiquidityWide helper function * add external contracts * sort imports * fix imports * improve comments * use exact values in tests * split uniswap contracts into v2/v3 folders * review changes * add weth and wbtc price in initialize function Uniswap V3 Exchange Adapter (#96) * add basic Uniswap V3 fixture * add createPool to fixture * add quoter * add getTokenOrder helper * add addLiquidityWide helper function * add external contracts * sort imports * fix imports * improve comments * use exact values in tests * split uniswap contracts into v2/v3 folders * add UniswapV3ExchangeAdapter * remove stray console log * fix comments * cleanup * add revert on path mismatch * add uniswap v3 tests to trade module integration tests * improve revert messages Add forked provider infrastructure and simple TradeModule / ExchangeAdapter tests (#64) Fix broken imports (#98) * v0.0.39 * fix imports Add uniswap v3 index exchange adapter (#89) * Add external Uniswap V3 contracts * Add UniswapV3 Index Exchange Adapter contract * Modify compiler-version in .solhint.json * Add tests * Fix coverage * Improve javadocs and add getEncodedTradePath() test * Use soldityPack in getEncodedTradePath test * Change compiler version to 0.6.10 * Add suggested changes * Remove getTradeEncodedPath function * Remove @uniswap/v3-periphery as dependency * Add @uniswap/v3-core as dependency * Use exactInputSingle and exactOutputSingle functions instead of exactInput and exactOutput * Move BytesLib to external/contracts/uniswap/v3 * Add Note to set exchange data in GIM * Remove @uniswap/v3-core dependency *Add suggested changes * Add getEncodedFeeData function and add suggested changes * Refactor tests to use UniswapV3 Fixture * Fix uniswap/v3/SwapRotuer ABI * Add integration tests with GIM * Trade DAI for WETH on UniswapV3 during rebalance * Trade WETH for WBTC on UniswapV3 during rebalance * Fix comment fix broken test (#102) Add AMMSplitter (#99) * add _getUniSplit function * add swapping * only rever when total output < min output * use better math for split * add tests * rename contracts and functions to be inline with spec * add multi hop support * add tradeExactOutput * clean up imports * shorten name * add javadocs * add getQuote function * clean up ratio calculation * remove hardhat console * add TradeSplitterExchangeAdapter * fix typo causing tests to break * add TradeSplitterIndexExchangeAdapter * improve coverage * increase coverage * refactor * remove redundant if in getQuote * improve reverts * improve coverage * move TradeSplitter into products * add TradeSplitterExchangeAdapter integration test * split getQuote into two functions for exact input/output * add TradeSplitter GIM integration tests * fix tests * make TradeSplitter adhere to the UniswapV2Router interface * use uniswap v2 adapters for trade splitter * cleanup * adhere to uniswap interface for getting quotes * change name of contracts * improve AMMSplitter tests * refactoring * fix bug with intermediary tokens with less than 18 decimals * refactor * add extra tests * update revert messages * improve comments * add events * use input and output tokens instead of path for events v0.0.41 (#103) change constructor parameters (#104) fix Felix comments (#105) Add Kyber V3 Index Exchange adapter (#101) * Add KyberV3 Index Exchange adapter contract * fix typo * Add Kyber V3 DMM fixture * Remove getPoolWithBestLiquidity() from adapter contract * Add tests for adapter contract * Add integration tests with GIM * Add tests for Kyber V3 DMM fixture * Fix bug * Fix bug in uniswap V3 fixture tests * Validate pool address in exchange adapter * Bump package to 0.0.43 * Move down pool address validation audit fixes (#108) Patch for real -> virtual -> real unit conversion. (#100) Patch for real -> virtual -> real unit conversion. Bump package. (#109) Update UniswapV2IndexExchangeAdapter to support two-hop trades (#110) * update adapter and tests * add integration test * improve comments * review changes bump package.json version number (#111) ClaimModule Audit fixes (#97) * low hanging audit changes * fix tests * audit changes * fix tests * improve tests * clean up contracts * use removeStorage * review changes SingularityNet migrator that burns unmigrated tokens, thus zeroing ou… (#113) SingularityNet migrator that burns unmigrated tokens, thus zeroing out position. Bump package. (#114) Address comments and add integration tests for Sushi wrap adapter
This is a set of small revisions suggested by the internal review of GeneralIndexModule. Each idea is expressed as a commit, so it can be considered on it's own and cherry-picked if useful.
The existing contract is highly optimized for gas - it minimizes state reads in loops as well as method encapsulation that would impose costs for extra function calls.
This version of the contract does the opposite - it introduces additional getters and generally ignores state read costs. For example,
_normalizedTargetUnits
is removed. It's also more aggressive about param validation. checks are added forsetExchange
(it's also validated during trades). Also storing this as a bytes32 hash, mirroring the IntegrationRegistry.The Berlin hardfork has made initial state reads for a location more expensive, but subsequent "warm" reads from the same place are much cheaper, changing the gas calculus a bit. Despite the inefficiencies introduced in this draft, the diff between versions suggests that gas costs increased only marginally overall. They would increase more in a module with a larger number of components.
Update I
Additional commits have been added after the review was finalized on Monday. Notable things are:
sendQuantity
andminReceiveQuantity
isSendFixed
toisSell
Update II: (Internal review remainders, review feedback, audit corrections)
TODO:
isSell
,minReceivedQuantity
toisFixedSend
,floatingQuantityLimit
Position.unitsMatchWithinRange
method for targets logic (invert)_getAggregateComponentsAndUnits
state mutability topure
removeModule
tests for preserved state, eval trader deletionraiseAssetTarget
Report shows original GeneralIndexModule vs. this PR (run on [email protected])
(Updated for most recent commits - April 20)
Deployments
Methods
Build Configuration