-
Notifications
You must be signed in to change notification settings - Fork 11
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
Position invariants #854
Position invariants #854
Conversation
* changes needed for contract verification (#764) * changes needed for contract verification * gotcha * Make NFT tokens claimable after `take`, `bucketTake`, `settle` actions (#763) * Add test failure * When ERC721.bucketTake always rebalance token ids from borrower to pool claimable array * Consistent take with bucketTake, always rebalance tokens * Check invariants in regression test * Always rebalance tokens on settle (settle could enter with 0 collateral but still with bad debt) * Changed epsilon from 1e16 to 1e17 in F1 and F2 invariants (#765) * Add variable token precision for ERC721Pool invariants (#755) * Add multiple precision of quote token in erc721Pool invariants * Add shebang and set -e option * Invariant framework improvements (#769) * Update forge library, set default env vars using envOr instead reading from env file * Remove InvariantsTestHelpers contract and move invariants helper functions to BaseInvariants * env cleanup for invariants * Update invariant testing scripts * Add skipTime in merge collateral handler * Add fuzzed time skip between kick and take/bucketTake --------- Co-authored-by: grandizzy <[email protected]> * Removing brownie TODOs as these tests won't be further expanded (#767) * ERC20 R1_R2_R3_R4_R5_R6_R7_R8 invariant failure (#771) * Add failing test * Change cutoff for deminimus check to 1 LP in a bucket for exchange rate diffs --------- Co-authored-by: mwc <[email protected]> * Erc721 CT2 invariant failure (#770) * Reproduce CT2 invariant failure * Add collateral that could be compensated in bucket 7388 when auction settled * Make sure MAX bucket not accounted twice. Fix test-regression target * Fix bucketTake invariant logic in place instead in CT2 invariant. Added regression test comments. * Fix CI, lock foundry version until resolution for foundry-rs/foundry#4835 --------- Co-authored-by: Ed Noepel <[email protected]> Co-authored-by: Prateek Gupta <[email protected]> Co-authored-by: mwc <[email protected]>
tests/forge/invariants/trace.log
Outdated
@@ -0,0 +1,17 @@ | |||
sender=0x00000000000000000000000000000000000006da addr=[tests/forge/invariants/PositionsAndRewards/handlers/RewardsHandler.sol:RewardsHandler]0xf535008760a9349da0650d92756d9a730c51c9ad calldata=claimRewards(uint256,uint256,uint256,uint256), args=[115792089237316195423570985008687907853269984665640564039457584007913129639933, 486888075223510502299880936499251496488108390102993365331518154575959314103, 1489390063300625330233647743808860618285793249553177794776030333650229253556, 29413051449830420745080834496160737679746193111333313068326] |
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.
Can remove this file with git rm
if not needed
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.
good call -> 9dec6df
.gitignore
Outdated
@@ -16,6 +16,7 @@ report/ | |||
keystore/ | |||
broadcast/ | |||
logFile.txt | |||
tests/forge/invariants/trace.log |
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.
nit: can update with a more general restriction *.log
since we shouldn't be committing any log files in this repo
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.
nice, fixed -> 9dec6df
} | ||
|
||
/**********************/ |
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.
I like the idea of sectioning, but would be helpful to be more specific - Rewards Calculations or similar. Also, this is probably best handled in a separate PR.
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.
agreed, separate PR
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.
Generally looks great! Just a few small comments. Also a general nit: many of the new files are missing a new line at the end of the file
fixed -> 2d93b7d |
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.
LGTM
_erc721impl = _erc721poolFactory.implementation(); | ||
_erc20pool = ERC20Pool(_erc20poolFactory.deployPool(address(_collateral), address(_quote), 0.05 * 10**18)); | ||
_pool = Pool(address(_erc20pool)); | ||
_position = new PositionManager(_erc20poolFactory, _erc721poolFactory); |
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.
nit: spacing
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.
fixed
|
||
|
||
|
||
function invariant_rewards_RW1() public useCurrentTimestamp { |
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.
that's fine, though easy to group them now in an invariant_rewards_RW1_RW2
as they almost use same values to compare, e.g.
function invariant_rewards_RW1_RW2() public useCurrentTimestamp {
// get current epoch (is incremented every kickReserve() call)
uint256 curEpoch = _pool.currentBurnEpoch();
// get rewards that have been claimed
uint256 claimedRewards = IBaseHandler(_handler).totalRewardPerEpoch(curEpoch);
// total ajna burned by the pool over the epoch
(, uint256 totalBurnedInPeriod,) = _getEpochInfo(address(_pool), curEpoch);
// stake rewards cap is 80% of total burned
uint256 stakeRewardsCap = Maths.wmul(totalBurnedInPeriod, 0.8 * 1e18);
// check claimed rewards < rewards cap
if (stakeRewardsCap != 0) require(claimedRewards < stakeRewardsCap, "Rewards invariant RW1");
// update rewards cap is 10% of total burned
uint256 updateRewardsCap = Maths.wmul(totalBurnedInPeriod, 0.1 * 1e18);
// check claimed rewards < rewards cap
if (updateRewardsCap != 0) require(claimedRewards < updateRewardsCap, "Rewards invariant RW2");
}
import { ERC20Pool } from 'src/ERC20Pool.sol'; | ||
|
||
import { UnboundedPositionsHandler } from './unbounded/UnboundedPositionsHandler.sol'; | ||
import { BaseERC20PoolHandler } from '../../ERC20Pool/handlers/unbounded/BaseERC20PoolHandler.sol'; |
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.
nit: spacing
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.
fixed
import { UnboundedPositionsHandler } from './unbounded/UnboundedPositionsHandler.sol'; | ||
import { BaseERC20PoolHandler } from '../../ERC20Pool/handlers/unbounded/BaseERC20PoolHandler.sol'; | ||
|
||
abstract contract PositionHandlerAbstract is UnboundedPositionsHandler { |
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.
what about Base
as we already use in BaseHandler
so BasePositionHandler
?
tests/forge/invariants/PositionsAndRewards/handlers/PositionHandlerAbstract.sol
Outdated
Show resolved
Hide resolved
// assert that underlying LP balance in PositionManager of fromIndex is less than or equal to preAction and deposit time in PositionManager is 0 | ||
(uint256 fromLps, uint256 fromDepositTime) = _position.getPositionInfo(tokenId_, fromIndex_); | ||
require(fromLps == 0); // difficult to estimate LPS, assert that it is less than | ||
require(fromDepositTime == 0); |
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.
revert message needed in require
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.
fixed -> c7c84e2
|
||
// assert that underlying LP balance in PositionManager of toIndex is increased and deposit time in PositionManager is updated | ||
(uint256 toLps, uint256 toDepositTime) = _position.getPositionInfo(tokenId_, toIndex_); | ||
require(toLps >= preActionToLps); // difficult to estimate LPS, assert that it is greater than |
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.
revert message needed in require
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.
fixed -> c7c84e2
(uint256 toLps, uint256 toDepositTime) = _position.getPositionInfo(tokenId_, toIndex_); | ||
require(toLps >= preActionToLps); // difficult to estimate LPS, assert that it is greater than | ||
(,uint256 postActionDepositTime)= _pool.lenderInfo(toIndex_, address(_position)); | ||
require(toDepositTime == postActionDepositTime); |
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.
revert message needed in require
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.
fixed -> c7c84e2
|
||
// assert that poolKey is returns zero address | ||
address poolAddress = _position.poolKey(tokenId_); | ||
require(poolAddress == address(0)); |
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.
revert message needed in require
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.
fixed -> c7c84e2
@@ -28,6 +28,13 @@ interface IBaseHandler { | |||
function increaseInReserves() external view returns(uint256); | |||
function decreaseInReserves() external view returns(uint256); | |||
|
|||
function totalRewardPerEpoch(uint256) external view returns(uint256); |
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.
suggest a different interface for pos / rewards handler
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.
fixed -> c7c84e2
*/ | ||
abstract contract BasePositionsHandler is BaseERC20PoolHandler { | ||
|
||
PositionManager internal _position; |
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.
please name this _positionManager
and _rewardsManager
for readability
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.
Yep, fixed -> 301a11c
* cleaned up requires, formally added more PositionManager invar * cleaned up requires, formally added more PositionManager invar * added logs * works with diff * cleanup --------- Co-authored-by: Ian Harvey <[email protected]>
06d90dc
to
8881b0f
Compare
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.
LGTM
Description of change
High level
PM1
-PM8
invariant checkRewards
andPosition
invariantsgetEpochInfo()
into "free" method