Skip to content
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

Merged
merged 67 commits into from
Jun 7, 2023
Merged

Position invariants #854

merged 67 commits into from
Jun 7, 2023

Conversation

ith-harvey
Copy link
Contributor

@ith-harvey ith-harvey commented May 29, 2023

Description of change

High level

  • Added PositionManager invariant scaffolding
  • Added asserts for PostionManger in handlers
  • Added PM1 - PM8 invariant check
  • Added forge test commands for Rewards and Position invariants
  • cleaned up invariant logging
  • turned getEpochInfo() into "free" method

Ian Harvey and others added 30 commits April 25, 2023 13:27
* 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]>
@ith-harvey ith-harvey requested a review from grandizzy June 4, 2023 21:23
@@ -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]
Copy link
Collaborator

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

Copy link
Contributor Author

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
Copy link
Collaborator

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice, fixed -> 9dec6df

}

/**********************/
Copy link
Collaborator

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed, separate PR

Copy link
Collaborator

@MikeHathaway MikeHathaway left a 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

@ith-harvey
Copy link
Contributor Author

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

Copy link
Collaborator

@MikeHathaway MikeHathaway left a 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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: spacing

Copy link
Contributor Author

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 {
Copy link
Contributor

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';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: spacing

Copy link
Contributor Author

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 {
Copy link
Contributor

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?

// 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);
Copy link
Contributor

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

Copy link
Contributor Author

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
Copy link
Contributor

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

Copy link
Contributor Author

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);
Copy link
Contributor

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

Copy link
Contributor Author

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));
Copy link
Contributor

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

Copy link
Contributor Author

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);
Copy link
Contributor

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

Copy link
Contributor Author

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;
Copy link
Contributor

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, fixed -> 301a11c

ith-harvey and others added 4 commits June 7, 2023 08:11
* 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]>
@ith-harvey ith-harvey requested a review from grandizzy June 7, 2023 14:35
Copy link
Contributor

@grandizzy grandizzy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@ith-harvey ith-harvey merged commit 089cb9d into develop Jun 7, 2023
@ith-harvey ith-harvey deleted the positions-only branch June 13, 2023 11:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants