From d66b0cedf906211ad1a53ea378c0e8fa8c408df3 Mon Sep 17 00:00:00 2001 From: neodaoist Date: Sat, 9 Sep 2023 14:01:48 +0300 Subject: [PATCH 01/14] forge install: SolPretty --- .gitmodules | 3 +++ lib/SolPretty | 1 + 2 files changed, 4 insertions(+) create mode 160000 lib/SolPretty diff --git a/.gitmodules b/.gitmodules index 558b49a..b617657 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "lib/solmate"] path = lib/solmate url = https://github.com/rari-capital/solmate +[submodule "lib/SolPretty"] + path = lib/SolPretty + url = https://github.com/devtooligan/SolPretty diff --git a/lib/SolPretty b/lib/SolPretty new file mode 160000 index 0000000..80f9820 --- /dev/null +++ b/lib/SolPretty @@ -0,0 +1 @@ +Subproject commit 80f98208b71093dff25c0e203a1de1551267a10f From ef4a12f5463ee03a030becbac067a832111f25a3 Mon Sep 17 00:00:00 2001 From: neodaoist Date: Sat, 9 Sep 2023 14:35:31 +0300 Subject: [PATCH 02/14] General setup --- foundry.toml | 2 +- .../IValoremOptionsClearinghouse.sol | 11 +++ ...aloremOptionsClearinghouse-v1.1.unit.t.sol | 89 +++++++++++++++++++ test/ValoremOptionsClearinghouse.unit.t.sol | 4 +- test/features/Clearinghouse-v1.1.feature | 44 +++++++++ 5 files changed, 147 insertions(+), 3 deletions(-) create mode 100644 test/ValoremOptionsClearinghouse-v1.1.unit.t.sol create mode 100644 test/features/Clearinghouse-v1.1.feature diff --git a/foundry.toml b/foundry.toml index 1de4d1c..1c3d327 100644 --- a/foundry.toml +++ b/foundry.toml @@ -2,7 +2,7 @@ src = 'src' out = 'out' libs = ['lib'] -remappings = ['forge-std/=lib/forge-std/src/', 'solmate/=lib/solmate/src/'] +remappings = ['forge-std/=lib/forge-std/src/', 'solmate/=lib/solmate/src/', 'SolPretty/=lib/SolPretty/src/'] [fuzz] seed = 7 diff --git a/src/interfaces/IValoremOptionsClearinghouse.sol b/src/interfaces/IValoremOptionsClearinghouse.sol index 2f05d5a..8e1a3cd 100644 --- a/src/interfaces/IValoremOptionsClearinghouse.sol +++ b/src/interfaces/IValoremOptionsClearinghouse.sol @@ -305,6 +305,7 @@ interface IValoremOptionsClearinghouse { uint96 nextClaimKey; } + // TODO add early redeem /** * @notice Data about a claim to a short position written on an option type. * When writing an amount of options of a particular type, the writer will be issued an ERC 1155 NFT @@ -477,10 +478,20 @@ interface IValoremOptionsClearinghouse { */ function write(uint256 tokenId, uint112 amount) external returns (uint256 claimId); + /*////////////////////////////////////////////////////////////// + // Net Offsetting Positions + //////////////////////////////////////////////////////////////*/ + + /** + * TODO + */ + // function net(uint256 optionid) external; + /*////////////////////////////////////////////////////////////// // Redeem Claims //////////////////////////////////////////////////////////////*/ + // TODO add early redeem /** * @notice Redeems a claim NFT, transfers the underlying/exercise tokens to the caller. * Can be called after option expiry timestamp (inclusive). diff --git a/test/ValoremOptionsClearinghouse-v1.1.unit.t.sol b/test/ValoremOptionsClearinghouse-v1.1.unit.t.sol new file mode 100644 index 0000000..5249bb2 --- /dev/null +++ b/test/ValoremOptionsClearinghouse-v1.1.unit.t.sol @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: BUSL 1.1 +// Valorem Labs Inc. (c) 2023. +pragma solidity 0.8.16; + +import "solmate/utils/FixedPointMathLib.sol"; +import "forge-std/Test.sol"; +import {pp, SolPretty} from "SolPretty/SolPretty.sol"; +import {IERC20} from "forge-std/interfaces/IERC20.sol"; + +import "./utils/BaseClearinghouseTest.sol"; + +/// @notice Unit tests for ValoremOptionsClearinghouse v1.1.0 +contract ValoremOptionsClearinghousev11UnitTest is BaseClearinghouseTest { + using SolPretty for string; + + /*////////////////////////////////////////////////////////////// + // Clearinghouse v1.1.0 + //////////////////////////////////////////////////////////////*/ + + function test_claimAssignmentStatus() public { + uint112 amountWritten = 5; + uint256 expectedFee = _calculateFee(testUnderlyingAmount * amountWritten); + uint256 expectedClaimId = testOptionId + 1; + + vm.prank(ALICE); + uint256 claimId = engine.write(testOptionId, amountWritten); + + // Post-write conditions + assertEq(claimId, expectedClaimId, "claimId"); + assertEq(engine.balanceOf(ALICE, claimId), 1, "Alice Claim NFT"); + assertEq(engine.balanceOf(ALICE, testOptionId), amountWritten, "Alice Option tokens"); + assertEq( + IERC20(testUnderlyingAsset).balanceOf(ALICE), + STARTING_BALANCE_WETH - (testUnderlyingAmount * amountWritten) - expectedFee, + "Alice underlying" + ); + assertEq(IERC20(testExerciseAsset).balanceOf(ALICE), STARTING_BALANCE, "Alice exercise"); // no change + assertEq(engine.feeBalance(testUnderlyingAsset), expectedFee, "Fee balance underlying"); + assertEq(engine.feeBalance(testExerciseAsset), 0, "Fee balance exercise"); // no fee assessed on exercise asset during write() + + // Unassigned + IValoremOptionsClearinghouse.Claim memory unassigned = engine.claim(claimId); + emit log("Unassigned Claim ---------"); + emit log_named_string("amountWritten", pp(unassigned.amountWritten, 18, 0)); + emit log_named_string("amountExercised", pp(unassigned.amountExercised, 18, 0)); + uint256 assignmentPercentage = unassigned.amountExercised / unassigned.amountWritten; + emit log_named_uint("percentage", assignmentPercentage); + // if amountExercised == 0, claim is unassigned + + // Partially Assigned + vm.prank(ALICE); + engine.safeTransferFrom(ALICE, BOB, testOptionId, 5, ""); + + vm.prank(BOB); + engine.exercise(testOptionId, 1); + + IValoremOptionsClearinghouse.Claim memory partiallyAssigned = engine.claim(claimId); + emit log("Partially Assigned Claim ---------"); + emit log_named_string("amountWritten", pp(partiallyAssigned.amountWritten, 18, 0)); + emit log_named_string("amountExercised", pp(partiallyAssigned.amountExercised, 18, 0)); + assignmentPercentage = partiallyAssigned.amountExercised / partiallyAssigned.amountWritten; + emit log_named_uint("percentage", assignmentPercentage); // TODO use scalar + // if amountExercised > 0 && amountWritten > amountExercised, claim is partially assigned + + // Fully Assigned + vm.prank(BOB); + engine.exercise(testOptionId, 4); + + IValoremOptionsClearinghouse.Claim memory fullyAssigned = engine.claim(claimId); + emit log("Fully Assigned Claim ---------"); + emit log_named_string("amountWritten", pp(fullyAssigned.amountWritten, 18, 0)); + emit log_named_string("amountExercised", pp(fullyAssigned.amountExercised, 18, 0)); + assignmentPercentage = fullyAssigned.amountExercised / fullyAssigned.amountWritten; + emit log_named_uint("percentage", assignmentPercentage); + // if amountWritten == amountExercised, claim is fully assigned + } + + /*////////////////////////////////////////////////////////////// + // net() + //////////////////////////////////////////////////////////////*/ + + // TODO + + /*////////////////////////////////////////////////////////////// + // redeem() early + //////////////////////////////////////////////////////////////*/ + + // TODO +} diff --git a/test/ValoremOptionsClearinghouse.unit.t.sol b/test/ValoremOptionsClearinghouse.unit.t.sol index e7119a5..0ce534c 100644 --- a/test/ValoremOptionsClearinghouse.unit.t.sol +++ b/test/ValoremOptionsClearinghouse.unit.t.sol @@ -554,7 +554,7 @@ contract ValoremOptionsClearinghouseUnitTest is BaseClearinghouseTest { vm.prank(ALICE); uint256 claimId = engine.write(testOptionId, amountWritten); - assertEq(claimId, testOptionId + 1, "claimId"); + assertEq(claimId, expectedClaimId, "claimId"); assertEq(engine.balanceOf(ALICE, claimId), 1, "Alice Claim NFT"); // 1 Claim NFT assertEq(engine.balanceOf(ALICE, testOptionId), amountWritten, "Alice Option tokens"); // 5 fungible Option tokens assertEq( @@ -1269,7 +1269,7 @@ contract ValoremOptionsClearinghouseUnitTest is BaseClearinghouseTest { assertEq(engine.balanceOf(other, optionId), 1, "Other option tokens"); // 1 left after 3 are burned on exercise } - function testRevert_exercise_whenCallerHasNotGrantedSufficientApprovalToengine() public { + function testRevert_exercise_whenCallerHasNotGrantedSufficientApprovalToEngine() public { uint256 optionId = engine.newOptionType({ underlyingAsset: address(ERC20A), underlyingAmount: 1 ether, diff --git a/test/features/Clearinghouse-v1.1.feature b/test/features/Clearinghouse-v1.1.feature new file mode 100644 index 0000000..3665a6d --- /dev/null +++ b/test/features/Clearinghouse-v1.1.feature @@ -0,0 +1,44 @@ +Feature: Net Offsetting Positions + + As an Option Writer, + I want to net offsetting long and short positions on the same instrument which I hold, + so that I can receive the underlying asset collateral back from the clearinghouse. + + # TODO incorporate 1e6 scalar for contract units + + Scenario: 1 Option and 1 Claim worth 1 unassigned Option + + Scenario: 10 Options and 1 Claim worth 10 unassigned Options + + Scenario: 9 Options and 1 Claim worth 10 unassigned Options + + Scenario: 11 Options and 1 Claim worth 10 unassigned Options + + @Revert + Scenario: 9 Options and 1 Claim worth 10 unassigned Options + + @Revert + Scenario: 10 Options and 1 Claim worth 9 unassigned Options + + @Revert + Scenario: 1 Option and 1 Claim worth 0 unassigned Options + + @Revert + Scenario: 0 Options and 1 Claim worth 10 unassigned Options + + @Revert + Scenario: 10 Options and 0 Claims + +Feature: Early Redeem of Fully Assigned Claims + + As an Option Writer, + I want to redeem a fully assigned Claim which I hold before the expiry timestamp, + so that I can receive the exercise asset collateral back from the clearinghouse. + + Scenario: 1 Fully Assigned Claim before expiry + + @Revert + Scenario: 1 Partially Assigned Claim before expiry + + @Revert + Scenario: 1 Unassigned Claim before expiry From 71be974f64b652ee645caedb3a1faa9104b0b3ec Mon Sep 17 00:00:00 2001 From: neodaoist Date: Sat, 9 Sep 2023 14:37:18 +0300 Subject: [PATCH 03/14] Add previous unit tests --- ...aloremOptionsClearinghouse-v1.1.unit.t.sol | 164 +++++++++++++++++- 1 file changed, 163 insertions(+), 1 deletion(-) diff --git a/test/ValoremOptionsClearinghouse-v1.1.unit.t.sol b/test/ValoremOptionsClearinghouse-v1.1.unit.t.sol index 5249bb2..10eef30 100644 --- a/test/ValoremOptionsClearinghouse-v1.1.unit.t.sol +++ b/test/ValoremOptionsClearinghouse-v1.1.unit.t.sol @@ -76,11 +76,173 @@ contract ValoremOptionsClearinghousev11UnitTest is BaseClearinghouseTest { } /*////////////////////////////////////////////////////////////// - // net() + // net(uint256 optionId) external //////////////////////////////////////////////////////////////*/ // TODO + // function test_close() public { + // uint256 balanceA = ERC20A.balanceOf(ALICE); + // uint256 balanceB = ERC20B.balanceOf(ALICE); + + // // Alice writes 10 options + // vm.startPrank(ALICE); + // uint256 optionId = engine.newOptionType({ + // underlyingAsset: address(ERC20A), + // underlyingAmount: 1 ether, + // exerciseAsset: address(ERC20B), + // exerciseAmount: 8 ether, + // exerciseTimestamp: uint40(block.timestamp), + // expiryTimestamp: uint40(block.timestamp + 30 days) + // }); + // uint256 claimId = engine.write(optionId, 10); + + // uint256 expectedWriteAmount = 10 * 1 ether; + + // assertEq(engine.balanceOf(ALICE, optionId), 10, "Alice option tokens before"); + // assertEq(engine.balanceOf(ALICE, claimId), 1, "Alice claim tokens before"); + // assertEq( + // ERC20A.balanceOf(ALICE), + // balanceA - expectedWriteAmount - _calculateFee(expectedWriteAmount), + // "Alice underlying asset before" + // ); + // assertEq(ERC20B.balanceOf(ALICE), balanceB, "Alice exercise asset before"); + + // // Alice closes offsetting positions after no Longs have been exercised + // engine.close(optionId); + + // assertEq(engine.balanceOf(ALICE, optionId), 0, "Alice option tokens after"); + // assertEq(engine.balanceOf(ALICE, claimId), 0, "Alice claim tokens after"); + // assertEq(ERC20A.balanceOf(ALICE), balanceA, "Alice underlying asset after"); + // assertEq(ERC20B.balanceOf(ALICE), balanceB, "Alice exercise asset after"); + // } + + // function test_close_whenPartiallyExercisedByWriter() public { + // uint256 balanceA = ERC20A.balanceOf(ALICE); + // uint256 balanceB = ERC20B.balanceOf(ALICE); + + // // Alice writes 10 options + // vm.startPrank(ALICE); + // uint256 optionId = engine.newOptionType({ + // underlyingAsset: address(ERC20A), + // underlyingAmount: 1 ether, + // exerciseAsset: address(ERC20B), + // exerciseAmount: 8 ether, + // exerciseTimestamp: uint40(block.timestamp), + // expiryTimestamp: uint40(block.timestamp + 30 days) + // }); + // uint256 claimId = engine.write(optionId, 10); + + // uint256 expectedWriteAmount = 10 * 1 ether; + // uint256 expectedExerciseAmount = 3 * 8 ether; + + // assertEq(engine.balanceOf(ALICE, optionId), 10, "Alice option tokens before"); + // assertEq(engine.balanceOf(ALICE, claimId), 1, "Alice claim tokens before"); + // assertEq( + // ERC20A.balanceOf(ALICE), + // balanceA - expectedWriteAmount - _calculateFee(expectedWriteAmount), + // "Alice underlying asset before" + // ); + // assertEq(ERC20B.balanceOf(ALICE), balanceB, "Alice exercise asset before"); + + // // Alice exercises 3 Longs + // engine.exercise(optionId, 3); + + // assertEq(engine.balanceOf(ALICE, optionId), 7, "Alice option tokens after exercise"); + // assertEq(engine.balanceOf(ALICE, claimId), 0, "Alice claim tokens after exercise"); + // assertEq( + // ERC20A.balanceOf(ALICE), + // balanceA - expectedWriteAmount - _calculateFee(expectedWriteAmount) + (3 * 1 ether), + // "Alice underlying asset after exercise" + // ); + // assertEq( + // ERC20B.balanceOf(ALICE), + // balanceB - expectedExerciseAmount - _calculateFee(expectedExerciseAmount), + // "Alice exercise asset after exercise" + // ); + + // // Alice closes remaining 7 Longs and claims collateral back from 3 Longs that she exercised + // engine.close(optionId); + + // assertEq(engine.balanceOf(ALICE, optionId), 0, "Alice option tokens after close"); + // assertEq(engine.balanceOf(ALICE, claimId), 0, "Alice claim tokens after close"); + // assertEq(ERC20A.balanceOf(ALICE), balanceA, "Alice underlying asset after close"); + // assertEq(ERC20B.balanceOf(ALICE), balanceB, "Alice exercise asset after close"); + // } + + // function test_close_whenPartiallyExercisedByOtherHolder() public { + // uint256 aliceBalanceA = ERC20A.balanceOf(ALICE); + // uint256 aliceBalanceB = ERC20B.balanceOf(ALICE); + // uint256 bobBalanceA = ERC20A.balanceOf(BOB); + // uint256 bobBalanceB = ERC20B.balanceOf(BOB); + + // // Alice writes 10 options + // vm.startPrank(ALICE); + // uint256 optionId = engine.newOptionType({ + // underlyingAsset: address(ERC20A), + // underlyingAmount: 1 ether, + // exerciseAsset: address(ERC20B), + // exerciseAmount: 8 ether, + // exerciseTimestamp: uint40(block.timestamp), + // expiryTimestamp: uint40(block.timestamp + 30 days) + // }); + // uint256 claimId = engine.write(optionId, 10); + + // uint256 expectedWriteAmount = 10 * 1 ether; + // uint256 expectedExerciseAmount = 3 * 8 ether; + + // assertEq(engine.balanceOf(ALICE, optionId), 10, "Alice option tokens before"); + // assertEq(engine.balanceOf(ALICE, claimId), 1, "Alice claim tokens before"); + // assertEq( + // ERC20A.balanceOf(ALICE), + // aliceBalanceA - expectedWriteAmount - _calculateFee(expectedWriteAmount), + // "Alice underlying asset before" + // ); + // assertEq(ERC20B.balanceOf(ALICE), aliceBalanceB, "Alice exercise asset before"); + + // // Alice transfers 3 Longs to Bob + // engine.safeTransferFrom(ALICE, BOB, optionId, 3, ""); + // vm.stopPrank(); + + // assertEq(engine.balanceOf(ALICE, optionId), 7, "Alice option tokens after transfer"); + // assertEq(engine.balanceOf(ALICE, claimId), 1, "Alice claim tokens after transfer"); + + // // Bob exercises 3 Longs + // vm.prank(BOB); + // engine.exercise(optionId, 3); + + // assertEq( + // ERC20A.balanceOf(ALICE), + // aliceBalanceA - expectedWriteAmount - _calculateFee(expectedWriteAmount), + // "Alice underlying asset after exercise" + // ); + // assertEq( + // ERC20B.balanceOf(ALICE), + // aliceBalanceB, + // "Alice exercise asset after exercise" + // ); + // assertEq( + // ERC20A.balanceOf(BOB), + // bobBalanceA + (3 * 1 ether), + // "Bob underlying asset after exercise" + // ); + // assertEq( + // ERC20B.balanceOf(BOB), + // bobBalanceB - expectedExerciseAmount - _calculateFee(expectedExerciseAmount), + // "Bob exercise asset after exercise" + // ); + + // // Alice closes remaining 7 Longs and claims collateral back from 3 Longs that Bob exercised + // engine.close(optionId); + + // assertEq(engine.balanceOf(ALICE, optionId), 0, "Alice option tokens after close"); + // assertEq(engine.balanceOf(ALICE, claimId), 0, "Alice claim tokens after close"); + // assertEq(ERC20A.balanceOf(ALICE), aliceBalanceA - expectedWriteAmount - _calculateFee(expectedWriteAmount) + (3 * 1 ether), "Alice underlying asset after close"); + // assertEq(ERC20B.balanceOf(ALICE), aliceBalanceB + expectedExerciseAmount, "Alice exercise asset after close"); + // assertEq(ERC20A.balanceOf(BOB), bobBalanceA, "Bob underlying asset after close"); + // assertEq(ERC20B.balanceOf(BOB), bobBalanceB, "Bob exercise asset after close"); + // } + /*////////////////////////////////////////////////////////////// // redeem() early //////////////////////////////////////////////////////////////*/ From 9ea95379adf03cb3ac9ab18bbc616001c881c384 Mon Sep 17 00:00:00 2001 From: neodaoist Date: Sat, 9 Sep 2023 16:47:45 +0300 Subject: [PATCH 04/14] Add initial impl of early redeem --- .solhint.json | 36 ++++++++--- src/TokenURIGenerator.sol | 1 + src/ValoremOptionsClearinghouse.sol | 9 +-- ...aloremOptionsClearinghouse-v1.1.unit.t.sol | 61 ++++++++++++++++++- test/ValoremOptionsClearinghouse.unit.t.sol | 20 +----- 5 files changed, 96 insertions(+), 31 deletions(-) diff --git a/.solhint.json b/.solhint.json index 2b5f85d..3a5be85 100644 --- a/.solhint.json +++ b/.solhint.json @@ -1,10 +1,28 @@ { - "extends": "solhint:recommended", - "rules": { - "compiler-version": ["error",">=0.8.0"], - "no-inline-assembly": ["off",">=0.8.0"], - "avoid-low-level-calls": ["off",">=0.8.0"], - "not-rely-on-time": ["off",">=0.8.0"], - "func-visibility": ["warn",{"ignoreConstructors":true}] - } -} + "extends": "solhint:recommended", + "rules": { + "compiler-version": [ + "error", + ">=0.8.0" + ], + "no-inline-assembly": [ + "off", + ">=0.8.0" + ], + "avoid-low-level-calls": [ + "off", + ">=0.8.0" + ], + "not-rely-on-time": [ + "off", + ">=0.8.0" + ], + "no-global-import": "off", + "func-visibility": [ + "warn", + { + "ignoreConstructors": true + } + ] + } +} \ No newline at end of file diff --git a/src/TokenURIGenerator.sol b/src/TokenURIGenerator.sol index 99a9807..b5ecba4 100644 --- a/src/TokenURIGenerator.sol +++ b/src/TokenURIGenerator.sol @@ -415,6 +415,7 @@ contract TokenURIGenerator is ITokenURIGenerator { buffer[i] = ALPHABET[value & 0xf]; value >>= 4; } + // solhint-disable custom-errors require(value == 0, "Strings: hex length insufficient"); return string(buffer); } diff --git a/src/ValoremOptionsClearinghouse.sol b/src/ValoremOptionsClearinghouse.sol index b6b6c1c..312401c 100644 --- a/src/ValoremOptionsClearinghouse.sol +++ b/src/ValoremOptionsClearinghouse.sol @@ -180,7 +180,7 @@ contract ValoremOptionsClearinghouse is ERC1155, IValoremOptionsClearinghouse { } /// @inheritdoc IValoremOptionsClearinghouse - function claim(uint256 claimId) external view returns (Claim memory claimInfo) { + function claim(uint256 claimId) public view returns (Claim memory claimInfo) { (uint160 optionKey, uint96 claimKey) = _decodeTokenId(claimId); if (!_isClaimInitialized(optionKey, claimKey)) { @@ -516,12 +516,13 @@ contract ValoremOptionsClearinghouse is ERC1155, IValoremOptionsClearinghouse { revert CallerDoesNotOwnClaimId(claimId); } - // Setup pointers to the option and info. + // Setup pointers to the option and claim info. OptionTypeState storage optionTypeState = optionTypeStates[optionKey]; Option memory optionRecord = optionTypeState.option; + Claim memory claimInfo = claim(claimId); // TODO can we combine this with Claim accounting below? - // Can't redeem until expiry. - if (optionRecord.expiryTimestamp > block.timestamp) { + // Can't redeem before expiry, unless Claim is fully assigned. + if (optionRecord.expiryTimestamp > block.timestamp && claimInfo.amountWritten > claimInfo.amountExercised) { revert ClaimTooSoon(claimId, optionRecord.expiryTimestamp); } diff --git a/test/ValoremOptionsClearinghouse-v1.1.unit.t.sol b/test/ValoremOptionsClearinghouse-v1.1.unit.t.sol index 10eef30..d4fed37 100644 --- a/test/ValoremOptionsClearinghouse-v1.1.unit.t.sol +++ b/test/ValoremOptionsClearinghouse-v1.1.unit.t.sol @@ -247,5 +247,64 @@ contract ValoremOptionsClearinghousev11UnitTest is BaseClearinghouseTest { // redeem() early //////////////////////////////////////////////////////////////*/ - // TODO + function test_redeem_whenBeforeExpiryAndClaimIsFullyAssigned() public { + vm.startPrank(ALICE); + uint256 claimId = engine.write(testOptionId, 10); + engine.safeTransferFrom(ALICE, BOB, testOptionId, 10, ""); + vm.stopPrank(); + + vm.warp(testExerciseTimestamp); + vm.prank(BOB); + engine.exercise(testOptionId, 10); + + // pre-redeem check + assertEq( + ERC20(testExerciseAsset).balanceOf(ALICE), STARTING_BALANCE, "Alice exercise asset balance, pre-redeem" + ); + + // vm.warp(testExpiryTimestamp); + vm.prank(ALICE); + engine.redeem(claimId); + + // post-redeem check + uint256 expectedPostRedeemBalance = STARTING_BALANCE + (testExerciseAmount * 10); + assertEq( + ERC20(testExerciseAsset).balanceOf(ALICE), + expectedPostRedeemBalance, + "Alice exercise asset balance, post-redeem" + ); + } + + function testRevert_redeem_whenBeforeExpiryAndClaimIsUnassigned() public { + vm.startPrank(ALICE); + uint256 claimId = engine.write(testOptionId, 2); + + vm.warp(testExpiryTimestamp - 1 seconds); + + vm.expectRevert( + abi.encodeWithSelector(IValoremOptionsClearinghouse.ClaimTooSoon.selector, claimId, testExpiryTimestamp) + ); + + engine.redeem(claimId); + vm.stopPrank(); + } + + function testRevert_redeem_whenBeforeExpiryAndClaimIsPartiallyAssigned() public { + vm.startPrank(ALICE); + uint256 claimId = engine.write(testOptionId, 2); + engine.safeTransferFrom(ALICE, BOB, testOptionId, 2, ""); + vm.stopPrank(); + + vm.warp(testExpiryTimestamp - 1 seconds); + + vm.prank(BOB); + engine.exercise(testOptionId, 1); + + vm.expectRevert( + abi.encodeWithSelector(IValoremOptionsClearinghouse.ClaimTooSoon.selector, claimId, testExpiryTimestamp) + ); + + vm.prank(ALICE); + engine.redeem(claimId); + } } diff --git a/test/ValoremOptionsClearinghouse.unit.t.sol b/test/ValoremOptionsClearinghouse.unit.t.sol index 0ce534c..603b645 100644 --- a/test/ValoremOptionsClearinghouse.unit.t.sol +++ b/test/ValoremOptionsClearinghouse.unit.t.sol @@ -751,7 +751,7 @@ contract ValoremOptionsClearinghouseUnitTest is BaseClearinghouseTest { // function redeem(uint256 claimId) external //////////////////////////////////////////////////////////////*/ - function test_redeem_whenUnexercised() public { + function test_redeem_whenUnassigned() public { uint112 amountWritten = 7; uint256 expectedUnderlyingAmount = testUnderlyingAmount * amountWritten; uint256 expectedUnderlyingFee = _calculateFee(expectedUnderlyingAmount); @@ -792,7 +792,7 @@ contract ValoremOptionsClearinghouseUnitTest is BaseClearinghouseTest { assertEq(DAILIKE.balanceOf(ALICE), STARTING_BALANCE, "Alice exercise post redeem"); // no change } - function test_redeem_whenPartiallyExercised() public { + function test_redeem_whenPartiallyAssigned() public { uint112 amountWritten = 7; uint112 amountExercised = 3; uint256 expectedUnderlyingFee = _calculateFee(testUnderlyingAmount); @@ -874,7 +874,7 @@ contract ValoremOptionsClearinghouseUnitTest is BaseClearinghouseTest { ); } - function test_redeem_whenFullyExercised() public { + function test_redeem_whenFullyAssigned() public { uint112 amountWritten = 7; uint112 amountExercised = 7; uint256 expectedUnderlyingFee = _calculateFee(testUnderlyingAmount); @@ -992,20 +992,6 @@ contract ValoremOptionsClearinghouseUnitTest is BaseClearinghouseTest { vm.stopPrank(); } - function testRevert_redeem_whenClaimTooSoon() public { - vm.startPrank(ALICE); - uint256 claimId = engine.write(testOptionId, 1); - - vm.warp(testExerciseTimestamp - 1 seconds); - - vm.expectRevert( - abi.encodeWithSelector(IValoremOptionsClearinghouse.ClaimTooSoon.selector, claimId, testExpiryTimestamp) - ); - - engine.redeem(claimId); - vm.stopPrank(); - } - /*////////////////////////////////////////////////////////////// // function exercise(uint256 optionId, uint112 amount) external //////////////////////////////////////////////////////////////*/ From 8e03ebad66fe74addb8e3a48a757ec4c3fab4dd5 Mon Sep 17 00:00:00 2001 From: neodaoist <3170590+neodaoist@users.noreply.github.com> Date: Sat, 9 Sep 2023 16:54:57 +0300 Subject: [PATCH 05/14] Update .solhint.json --- .solhint.json | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/.solhint.json b/.solhint.json index 2b5f85d..af5e41e 100644 --- a/.solhint.json +++ b/.solhint.json @@ -1,10 +1,28 @@ { - "extends": "solhint:recommended", - "rules": { - "compiler-version": ["error",">=0.8.0"], - "no-inline-assembly": ["off",">=0.8.0"], - "avoid-low-level-calls": ["off",">=0.8.0"], - "not-rely-on-time": ["off",">=0.8.0"], - "func-visibility": ["warn",{"ignoreConstructors":true}] - } + "extends": "solhint:recommended", + "rules": { + "compiler-version": [ + "error", + ">=0.8.0" + ], + "no-inline-assembly": [ + "off", + ">=0.8.0" + ], + "avoid-low-level-calls": [ + "off", + ">=0.8.0" + ], + "not-rely-on-time": [ + "off", + ">=0.8.0" + ], + "no-global-import": "off", + "func-visibility": [ + "warn", + { + "ignoreConstructors": true + } + ] + } } From 067d6f88305662b84c3d418599a48e7f52bbb33c Mon Sep 17 00:00:00 2001 From: neodaoist <3170590+neodaoist@users.noreply.github.com> Date: Sat, 9 Sep 2023 16:55:24 +0300 Subject: [PATCH 06/14] Update TokenURIGenerator.sol --- src/TokenURIGenerator.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/TokenURIGenerator.sol b/src/TokenURIGenerator.sol index 99a9807..d5b7a45 100644 --- a/src/TokenURIGenerator.sol +++ b/src/TokenURIGenerator.sol @@ -415,6 +415,8 @@ contract TokenURIGenerator is ITokenURIGenerator { buffer[i] = ALPHABET[value & 0xf]; value >>= 4; } + + // solhint-disable custom-errors require(value == 0, "Strings: hex length insufficient"); return string(buffer); } From 6eb37ad67796219e44faf2af873b308a07c57e42 Mon Sep 17 00:00:00 2001 From: neodaoist Date: Sat, 9 Sep 2023 16:56:22 +0300 Subject: [PATCH 07/14] Smol --- src/TokenURIGenerator.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/src/TokenURIGenerator.sol b/src/TokenURIGenerator.sol index b5ecba4..3eb8e09 100644 --- a/src/TokenURIGenerator.sol +++ b/src/TokenURIGenerator.sol @@ -415,6 +415,7 @@ contract TokenURIGenerator is ITokenURIGenerator { buffer[i] = ALPHABET[value & 0xf]; value >>= 4; } + // solhint-disable custom-errors require(value == 0, "Strings: hex length insufficient"); return string(buffer); From 2424468710aa526fae91febb903e8a9ec029d2fc Mon Sep 17 00:00:00 2001 From: neodaoist Date: Tue, 12 Sep 2023 19:24:08 +0300 Subject: [PATCH 08/14] lint --- src/TokenURIGenerator.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TokenURIGenerator.sol b/src/TokenURIGenerator.sol index 3eb8e09..d5b7a45 100644 --- a/src/TokenURIGenerator.sol +++ b/src/TokenURIGenerator.sol @@ -415,7 +415,7 @@ contract TokenURIGenerator is ITokenURIGenerator { buffer[i] = ALPHABET[value & 0xf]; value >>= 4; } - + // solhint-disable custom-errors require(value == 0, "Strings: hex length insufficient"); return string(buffer); From 63ec13f5307137628a9a296975e6581583184acd Mon Sep 17 00:00:00 2001 From: neodaoist Date: Tue, 12 Sep 2023 19:25:56 +0300 Subject: [PATCH 09/14] snapshot --- .gas-snapshot | 107 ++++++++++++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 52 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index 210787b..898e28e 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,82 +1,85 @@ -ValoremOptionsClearinghouseFuzzTest:test_fuzzExercise(uint112,uint112) (runs: 256, μ: 363079, ~: 366353) +ValoremOptionsClearinghouseFuzzTest:test_fuzzExercise(uint112,uint112) (runs: 256, μ: 363675, ~: 366353) ValoremOptionsClearinghouseFuzzTest:test_fuzzNewOptionType(uint96,uint96,uint40,uint40) (runs: 256, μ: 130922, ~: 130922) ValoremOptionsClearinghouseFuzzTest:test_fuzzWrite(uint112) (runs: 256, μ: 284216, ~: 284216) -ValoremOptionsClearinghouseFuzzTest:test_fuzzWriteExerciseRedeem(uint32) (runs: 256, μ: 9435521, ~: 9506149) +ValoremOptionsClearinghouseFuzzTest:test_fuzzWriteExerciseRedeem(uint32) (runs: 256, μ: 9524189, ~: 9614090) ValoremOptionsClearinghouseIntegrationTest:test_integrationAddOptionsToExistingClaim() (gas: 400435) -ValoremOptionsClearinghouseIntegrationTest:test_integrationDustHandling() (gas: 905028) +ValoremOptionsClearinghouseIntegrationTest:test_integrationDustHandling() (gas: 920361) ValoremOptionsClearinghouseIntegrationTest:test_integrationFairAssignment() (gas: 603589) ValoremOptionsClearinghouseIntegrationTest:test_integrationRandomAssignment() (gas: 906223) ValoremOptionsClearinghouseIntegrationTest:test_integrationSweepFeesWhenFeesAccruedForExercise() (gas: 1418985) ValoremOptionsClearinghouseIntegrationTest:test_integrationSweepFeesWhenFeesAccruedForWrite() (gas: 1343568) ValoremOptionsClearinghouseIntegrationTest:test_integrationWriteExerciseAddBuckets() (gas: 1062312) -ValoremOptionsClearinghouseInvariantTest:invariant_erc20_balances() (runs: 10, calls: 10000, reverts: 5042) -ValoremOptionsClearinghouseInvariantTest:invariant_options_written_match_claims() (runs: 10, calls: 10000, reverts: 4917) -ValoremOptionsClearinghouseInvariantTest:invariant_positions_accounting() (runs: 10, calls: 10000, reverts: 5034) -ValoremOptionsClearinghouseUnitTest:testRevert_acceptFeeTo_whenNotPendingFeeTo() (gas: 35323) -ValoremOptionsClearinghouseUnitTest:testRevert_claim_whenClaimDoesNotExist() (gas: 13769) -ValoremOptionsClearinghouseUnitTest:testRevert_construction_whenFeeToIsZeroAddress() (gas: 2055299) -ValoremOptionsClearinghouseUnitTest:testRevert_construction_whenTokenURIGeneratorIsZeroAddress() (gas: 39981) -ValoremOptionsClearinghouseUnitTest:testRevert_exercise_whenCallerHasNotGrantedSufficientApprovalToengine() (gas: 584793) -ValoremOptionsClearinghouseUnitTest:testRevert_exercise_whenCallerHoldsInsufficientExerciseAsset() (gas: 582992) +ValoremOptionsClearinghouseInvariantTest:invariant_erc20_balances() (runs: 10, calls: 10000, reverts: 5019) +ValoremOptionsClearinghouseInvariantTest:invariant_options_written_match_claims() (runs: 10, calls: 10000, reverts: 4965) +ValoremOptionsClearinghouseInvariantTest:invariant_positions_accounting() (runs: 10, calls: 10000, reverts: 4922) +ValoremOptionsClearinghouseUnitTest:testRevert_acceptFeeTo_whenNotPendingFeeTo() (gas: 35301) +ValoremOptionsClearinghouseUnitTest:testRevert_claim_whenClaimDoesNotExist() (gas: 14648) +ValoremOptionsClearinghouseUnitTest:testRevert_construction_whenFeeToIsZeroAddress() (gas: 2055329) +ValoremOptionsClearinghouseUnitTest:testRevert_construction_whenTokenURIGeneratorIsZeroAddress() (gas: 39989) +ValoremOptionsClearinghouseUnitTest:testRevert_exercise_whenCallerHasNotGrantedSufficientApprovalToEngine() (gas: 584824) +ValoremOptionsClearinghouseUnitTest:testRevert_exercise_whenCallerHoldsInsufficientExerciseAsset() (gas: 582959) ValoremOptionsClearinghouseUnitTest:testRevert_exercise_whenCallerHoldsInsufficientOptions() (gas: 264635) ValoremOptionsClearinghouseUnitTest:testRevert_exercise_whenExerciseTooEarly() (gas: 268095) ValoremOptionsClearinghouseUnitTest:testRevert_exercise_whenExpiredOption() (gas: 267890) ValoremOptionsClearinghouseUnitTest:testRevert_exercise_whenInvalidOption() (gas: 254368) -ValoremOptionsClearinghouseUnitTest:testRevert_newOptionType_whenExerciseWindowTooShort() (gas: 23334) +ValoremOptionsClearinghouseUnitTest:testRevert_newOptionType_whenExerciseWindowTooShort() (gas: 23356) ValoremOptionsClearinghouseUnitTest:testRevert_newOptionType_whenExpiryWindowTooShort() (gas: 24821) -ValoremOptionsClearinghouseUnitTest:testRevert_newOptionType_whenInvalidAssets() (gas: 21521) +ValoremOptionsClearinghouseUnitTest:testRevert_newOptionType_whenInvalidAssets() (gas: 21454) ValoremOptionsClearinghouseUnitTest:testRevert_newOptionType_whenOptionsTypeExists() (gas: 26485) -ValoremOptionsClearinghouseUnitTest:testRevert_newOptionType_whenTotalSuppliesAreTooLowToExercise() (gas: 44348) -ValoremOptionsClearinghouseUnitTest:testRevert_option_whenOptionDoesNotExist() (gas: 12493) -ValoremOptionsClearinghouseUnitTest:testRevert_position_whenExpiredOption() (gas: 19238) -ValoremOptionsClearinghouseUnitTest:testRevert_position_whenTokenNotFound() (gas: 11847) -ValoremOptionsClearinghouseUnitTest:testRevert_redeem_whenCallerDoesNotOwnClaimId() (gas: 247148) -ValoremOptionsClearinghouseUnitTest:testRevert_redeem_whenClaimTooSoon() (gas: 260127) -ValoremOptionsClearinghouseUnitTest:testRevert_redeem_whenInvalidClaim() (gas: 9432) +ValoremOptionsClearinghouseUnitTest:testRevert_newOptionType_whenTotalSuppliesAreTooLowToExercise() (gas: 45213) +ValoremOptionsClearinghouseUnitTest:testRevert_option_whenOptionDoesNotExist() (gas: 13355) +ValoremOptionsClearinghouseUnitTest:testRevert_position_whenExpiredOption() (gas: 20053) +ValoremOptionsClearinghouseUnitTest:testRevert_position_whenTokenNotFound() (gas: 12705) +ValoremOptionsClearinghouseUnitTest:testRevert_redeem_whenCallerDoesNotOwnClaimId() (gas: 249313) +ValoremOptionsClearinghouseUnitTest:testRevert_redeem_whenInvalidClaim() (gas: 9520) ValoremOptionsClearinghouseUnitTest:testRevert_setFeeTo_whenNotCurrentFeeTo() (gas: 11919) ValoremOptionsClearinghouseUnitTest:testRevert_setFeeTo_whenZeroAddress() (gas: 11641) -ValoremOptionsClearinghouseUnitTest:testRevert_setFeesEnabled_whenNotFeeTo() (gas: 11843) -ValoremOptionsClearinghouseUnitTest:testRevert_setTokenURIGenerator_whenNotCurrentFeeTo() (gas: 11911) -ValoremOptionsClearinghouseUnitTest:testRevert_setTokenURIGenerator_whenZeroAddress() (gas: 11653) -ValoremOptionsClearinghouseUnitTest:testRevert_sweepFees_whenNotFeeTo() (gas: 16949) -ValoremOptionsClearinghouseUnitTest:testRevert_uri_whenTokenNotFound() (gas: 18686) -ValoremOptionsClearinghouseUnitTest:testRevert_write_whenAmountWrittenCannotBeZero() (gas: 10763) -ValoremOptionsClearinghouseUnitTest:testRevert_write_whenCallerDoesNotOwnClaimId() (gas: 261825) -ValoremOptionsClearinghouseUnitTest:testRevert_write_whenCallerHasNotGrantedSufficientApprovalToengine() (gas: 685646) -ValoremOptionsClearinghouseUnitTest:testRevert_write_whenCallerHoldsInsufficientExerciseAsset() (gas: 685705) -ValoremOptionsClearinghouseUnitTest:testRevert_write_whenExpiredOption() (gas: 16935) -ValoremOptionsClearinghouseUnitTest:testRevert_write_whenInvalidOption() (gas: 13604) -ValoremOptionsClearinghouseUnitTest:test_claim_whenWrittenMultiple() (gas: 383202) -ValoremOptionsClearinghouseUnitTest:test_claim_whenWrittenMultipleTimesOnMultipleClaims() (gas: 458203) -ValoremOptionsClearinghouseUnitTest:test_claim_whenWrittenOnce() (gas: 303666) -ValoremOptionsClearinghouseUnitTest:test_exercise() (gas: 384012) +ValoremOptionsClearinghouseUnitTest:testRevert_setFeesEnabled_whenNotFeeTo() (gas: 11821) +ValoremOptionsClearinghouseUnitTest:testRevert_setTokenURIGenerator_whenNotCurrentFeeTo() (gas: 11889) +ValoremOptionsClearinghouseUnitTest:testRevert_setTokenURIGenerator_whenZeroAddress() (gas: 11609) +ValoremOptionsClearinghouseUnitTest:testRevert_sweepFees_whenNotFeeTo() (gas: 16927) +ValoremOptionsClearinghouseUnitTest:testRevert_uri_whenTokenNotFound() (gas: 20262) +ValoremOptionsClearinghouseUnitTest:testRevert_write_whenAmountWrittenCannotBeZero() (gas: 10676) +ValoremOptionsClearinghouseUnitTest:testRevert_write_whenCallerDoesNotOwnClaimId() (gas: 261803) +ValoremOptionsClearinghouseUnitTest:testRevert_write_whenCallerHasNotGrantedSufficientApprovalToengine() (gas: 687624) +ValoremOptionsClearinghouseUnitTest:testRevert_write_whenCallerHoldsInsufficientExerciseAsset() (gas: 687659) +ValoremOptionsClearinghouseUnitTest:testRevert_write_whenExpiredOption() (gas: 16957) +ValoremOptionsClearinghouseUnitTest:testRevert_write_whenInvalidOption() (gas: 13626) +ValoremOptionsClearinghouseUnitTest:test_claim_whenWrittenMultiple() (gas: 387402) +ValoremOptionsClearinghouseUnitTest:test_claim_whenWrittenMultipleTimesOnMultipleClaims() (gas: 458225) +ValoremOptionsClearinghouseUnitTest:test_claim_whenWrittenOnce() (gas: 306556) +ValoremOptionsClearinghouseUnitTest:test_exercise() (gas: 383968) ValoremOptionsClearinghouseUnitTest:test_exercise_whenExercisingMultipleTimes() (gas: 425505) ValoremOptionsClearinghouseUnitTest:test_feeBalance_whenFeeOff() (gas: 267101) ValoremOptionsClearinghouseUnitTest:test_feeBalance_whenFeeOn() (gas: 323819) -ValoremOptionsClearinghouseUnitTest:test_feeBalance_whenMinimum() (gas: 401587) +ValoremOptionsClearinghouseUnitTest:test_feeBalance_whenMinimum() (gas: 401565) ValoremOptionsClearinghouseUnitTest:test_feeBps() (gas: 5644) -ValoremOptionsClearinghouseUnitTest:test_feeTo() (gas: 7781) +ValoremOptionsClearinghouseUnitTest:test_feeTo() (gas: 7737) ValoremOptionsClearinghouseUnitTest:test_feesEnabled() (gas: 7684) -ValoremOptionsClearinghouseUnitTest:test_newOptionType() (gas: 130017) -ValoremOptionsClearinghouseUnitTest:test_option_returnsOptionInfo() (gas: 25650) +ValoremOptionsClearinghouseUnitTest:test_newOptionType() (gas: 130083) +ValoremOptionsClearinghouseUnitTest:test_option_returnsOptionInfo() (gas: 25672) ValoremOptionsClearinghouseUnitTest:test_position_whenFullyExercisedClaim() (gas: 302781) -ValoremOptionsClearinghouseUnitTest:test_position_whenOption() (gas: 30855) -ValoremOptionsClearinghouseUnitTest:test_position_whenPartiallyExercisedClaim() (gas: 427836) +ValoremOptionsClearinghouseUnitTest:test_position_whenOption() (gas: 31743) +ValoremOptionsClearinghouseUnitTest:test_position_whenPartiallyExercisedClaim() (gas: 427858) ValoremOptionsClearinghouseUnitTest:test_position_whenUnexercisedClaim() (gas: 263939) -ValoremOptionsClearinghouseUnitTest:test_redeem_whenFullyExercised() (gas: 333102) -ValoremOptionsClearinghouseUnitTest:test_redeem_whenPartiallyExercised() (gas: 343924) -ValoremOptionsClearinghouseUnitTest:test_redeem_whenUnexercised() (gas: 235840) -ValoremOptionsClearinghouseUnitTest:test_setFeeToAndAcceptFeeTo() (gas: 29510) +ValoremOptionsClearinghouseUnitTest:test_redeem_whenFullyAssigned() (gas: 335329) +ValoremOptionsClearinghouseUnitTest:test_redeem_whenPartiallyAssigned() (gas: 346683) +ValoremOptionsClearinghouseUnitTest:test_redeem_whenUnassigned() (gas: 238600) +ValoremOptionsClearinghouseUnitTest:test_setFeeToAndAcceptFeeTo() (gas: 29546) ValoremOptionsClearinghouseUnitTest:test_setFeeToAndAcceptFeeTo_multipleTimes() (gas: 50411) -ValoremOptionsClearinghouseUnitTest:test_setFeesEnabled() (gas: 20514) +ValoremOptionsClearinghouseUnitTest:test_setFeesEnabled() (gas: 20581) ValoremOptionsClearinghouseUnitTest:test_setTokenURIGenerator() (gas: 2035989) -ValoremOptionsClearinghouseUnitTest:test_sweepFees() (gas: 376903) -ValoremOptionsClearinghouseUnitTest:test_sweepFees_whenNoFees() (gas: 53303) +ValoremOptionsClearinghouseUnitTest:test_sweepFees() (gas: 376859) +ValoremOptionsClearinghouseUnitTest:test_sweepFees_whenNoFees() (gas: 53259) ValoremOptionsClearinghouseUnitTest:test_tokenType_returnsClaim() (gas: 253539) ValoremOptionsClearinghouseUnitTest:test_tokenType_returnsNone() (gas: 7980) -ValoremOptionsClearinghouseUnitTest:test_tokenType_returnsOption() (gas: 10216) -ValoremOptionsClearinghouseUnitTest:test_tokenURIGenerator() (gas: 9963) +ValoremOptionsClearinghouseUnitTest:test_tokenType_returnsOption() (gas: 10128) +ValoremOptionsClearinghouseUnitTest:test_tokenURIGenerator() (gas: 9941) ValoremOptionsClearinghouseUnitTest:test_uri() (gas: 479483) ValoremOptionsClearinghouseUnitTest:test_write_whenExistingClaim() (gas: 301062) ValoremOptionsClearinghouseUnitTest:test_write_whenFeeOff() (gas: 259288) -ValoremOptionsClearinghouseUnitTest:test_write_whenNewClaim() (gas: 280712) \ No newline at end of file +ValoremOptionsClearinghouseUnitTest:test_write_whenNewClaim() (gas: 280534) +ValoremOptionsClearinghousev11UnitTest:testRevert_redeem_whenBeforeExpiryAndClaimIsPartiallyAssigned() (gas: 352537) +ValoremOptionsClearinghousev11UnitTest:testRevert_redeem_whenBeforeExpiryAndClaimIsUnassigned() (gas: 262772) +ValoremOptionsClearinghousev11UnitTest:test_claimAssignmentStatus() (gas: 394240) +ValoremOptionsClearinghousev11UnitTest:test_redeem_whenBeforeExpiryAndClaimIsFullyAssigned() (gas: 312642) \ No newline at end of file From 84fc1ea62bf46c329286d9c68f637ec2fd1eb102 Mon Sep 17 00:00:00 2001 From: neodaoist Date: Wed, 13 Sep 2023 17:58:48 +0300 Subject: [PATCH 10/14] Remove solpretty for time being --- .gas-snapshot | 2 +- ...aloremOptionsClearinghouse-v1.1.unit.t.sol | 39 +++++++++---------- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index 898e28e..c519c4f 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -81,5 +81,5 @@ ValoremOptionsClearinghouseUnitTest:test_write_whenFeeOff() (gas: 259288) ValoremOptionsClearinghouseUnitTest:test_write_whenNewClaim() (gas: 280534) ValoremOptionsClearinghousev11UnitTest:testRevert_redeem_whenBeforeExpiryAndClaimIsPartiallyAssigned() (gas: 352537) ValoremOptionsClearinghousev11UnitTest:testRevert_redeem_whenBeforeExpiryAndClaimIsUnassigned() (gas: 262772) -ValoremOptionsClearinghousev11UnitTest:test_claimAssignmentStatus() (gas: 394240) +ValoremOptionsClearinghousev11UnitTest:test_claimAssignmentStatus() (gas: 342942) ValoremOptionsClearinghousev11UnitTest:test_redeem_whenBeforeExpiryAndClaimIsFullyAssigned() (gas: 312642) \ No newline at end of file diff --git a/test/ValoremOptionsClearinghouse-v1.1.unit.t.sol b/test/ValoremOptionsClearinghouse-v1.1.unit.t.sol index d4fed37..86c8c88 100644 --- a/test/ValoremOptionsClearinghouse-v1.1.unit.t.sol +++ b/test/ValoremOptionsClearinghouse-v1.1.unit.t.sol @@ -4,15 +4,12 @@ pragma solidity 0.8.16; import "solmate/utils/FixedPointMathLib.sol"; import "forge-std/Test.sol"; -import {pp, SolPretty} from "SolPretty/SolPretty.sol"; import {IERC20} from "forge-std/interfaces/IERC20.sol"; import "./utils/BaseClearinghouseTest.sol"; /// @notice Unit tests for ValoremOptionsClearinghouse v1.1.0 contract ValoremOptionsClearinghousev11UnitTest is BaseClearinghouseTest { - using SolPretty for string; - /*////////////////////////////////////////////////////////////// // Clearinghouse v1.1.0 //////////////////////////////////////////////////////////////*/ @@ -39,12 +36,12 @@ contract ValoremOptionsClearinghousev11UnitTest is BaseClearinghouseTest { assertEq(engine.feeBalance(testExerciseAsset), 0, "Fee balance exercise"); // no fee assessed on exercise asset during write() // Unassigned - IValoremOptionsClearinghouse.Claim memory unassigned = engine.claim(claimId); - emit log("Unassigned Claim ---------"); - emit log_named_string("amountWritten", pp(unassigned.amountWritten, 18, 0)); - emit log_named_string("amountExercised", pp(unassigned.amountExercised, 18, 0)); - uint256 assignmentPercentage = unassigned.amountExercised / unassigned.amountWritten; - emit log_named_uint("percentage", assignmentPercentage); + // IValoremOptionsClearinghouse.Claim memory unassigned = engine.claim(claimId); + // emit log("Unassigned Claim ---------"); + // emit log_named_string("amountWritten", pp(unassigned.amountWritten, 18, 0)); + // emit log_named_string("amountExercised", pp(unassigned.amountExercised, 18, 0)); + // uint256 assignmentPercentage = unassigned.amountExercised / unassigned.amountWritten; + // emit log_named_uint("percentage", assignmentPercentage); // if amountExercised == 0, claim is unassigned // Partially Assigned @@ -54,24 +51,24 @@ contract ValoremOptionsClearinghousev11UnitTest is BaseClearinghouseTest { vm.prank(BOB); engine.exercise(testOptionId, 1); - IValoremOptionsClearinghouse.Claim memory partiallyAssigned = engine.claim(claimId); - emit log("Partially Assigned Claim ---------"); - emit log_named_string("amountWritten", pp(partiallyAssigned.amountWritten, 18, 0)); - emit log_named_string("amountExercised", pp(partiallyAssigned.amountExercised, 18, 0)); - assignmentPercentage = partiallyAssigned.amountExercised / partiallyAssigned.amountWritten; - emit log_named_uint("percentage", assignmentPercentage); // TODO use scalar + // IValoremOptionsClearinghouse.Claim memory partiallyAssigned = engine.claim(claimId); + // emit log("Partially Assigned Claim ---------"); + // emit log_named_string("amountWritten", pp(partiallyAssigned.amountWritten, 18, 0)); + // emit log_named_string("amountExercised", pp(partiallyAssigned.amountExercised, 18, 0)); + // assignmentPercentage = partiallyAssigned.amountExercised / partiallyAssigned.amountWritten; + // emit log_named_uint("percentage", assignmentPercentage); // TODO use scalar // if amountExercised > 0 && amountWritten > amountExercised, claim is partially assigned // Fully Assigned vm.prank(BOB); engine.exercise(testOptionId, 4); - IValoremOptionsClearinghouse.Claim memory fullyAssigned = engine.claim(claimId); - emit log("Fully Assigned Claim ---------"); - emit log_named_string("amountWritten", pp(fullyAssigned.amountWritten, 18, 0)); - emit log_named_string("amountExercised", pp(fullyAssigned.amountExercised, 18, 0)); - assignmentPercentage = fullyAssigned.amountExercised / fullyAssigned.amountWritten; - emit log_named_uint("percentage", assignmentPercentage); + // IValoremOptionsClearinghouse.Claim memory fullyAssigned = engine.claim(claimId); + // emit log("Fully Assigned Claim ---------"); + // emit log_named_string("amountWritten", pp(fullyAssigned.amountWritten, 18, 0)); + // emit log_named_string("amountExercised", pp(fullyAssigned.amountExercised, 18, 0)); + // assignmentPercentage = fullyAssigned.amountExercised / fullyAssigned.amountWritten; + // emit log_named_uint("percentage", assignmentPercentage); // if amountWritten == amountExercised, claim is fully assigned } From da4e13eeb1bd480c129a1caa8432bce3fa6c2e64 Mon Sep 17 00:00:00 2001 From: neodaoist Date: Wed, 13 Sep 2023 18:00:59 +0300 Subject: [PATCH 11/14] Remove solpretty lib --- .gitmodules | 3 --- lib/SolPretty | 1 - 2 files changed, 4 deletions(-) delete mode 160000 lib/SolPretty diff --git a/.gitmodules b/.gitmodules index b617657..558b49a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,6 +4,3 @@ [submodule "lib/solmate"] path = lib/solmate url = https://github.com/rari-capital/solmate -[submodule "lib/SolPretty"] - path = lib/SolPretty - url = https://github.com/devtooligan/SolPretty diff --git a/lib/SolPretty b/lib/SolPretty deleted file mode 160000 index 80f9820..0000000 --- a/lib/SolPretty +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 80f98208b71093dff25c0e203a1de1551267a10f From ef9258c90bc692a500b743ad8063bff837778ad5 Mon Sep 17 00:00:00 2001 From: neodaoist Date: Tue, 19 Sep 2023 16:41:29 +0300 Subject: [PATCH 12/14] chore: Add custom gas snapshot format --- .gas-snapshot-custom | 86 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 .gas-snapshot-custom diff --git a/.gas-snapshot-custom b/.gas-snapshot-custom new file mode 100644 index 0000000..ae37902 --- /dev/null +++ b/.gas-snapshot-custom @@ -0,0 +1,86 @@ +| src/TokenURIGenerator.sol:TokenURIGenerator contract | | | | | | +|------------------------------------------------------|-----------------|--------|--------|--------|---------| +| Deployment Cost | Deployment Size | | | | | +| 1982298 | 9933 | | | | | +| Function Name | min | avg | median | max | # calls | +| constructTokenURI | 420115 | 420115 | 420115 | 420115 | 1 | +| src/ValoremOptionsClearinghouse.sol:ValoremOptionsClearinghouse contract | | | | | | +|--------------------------------------------------------------------------|-----------------|--------|--------|--------|---------| +| Deployment Cost | Deployment Size | | | | | +| 3281087 | 16499 | | | | | +| Function Name | min | avg | median | max | # calls | +| acceptFeeTo | 585 | 2455 | 2705 | 3825 | 4 | +| balanceOf | 619 | 2583 | 2619 | 2619 | 9722 | +| claim | 831 | 2832 | 2831 | 4660 | 4495 | +| exercise | 513 | 31318 | 20848 | 80748 | 94 | +| feeBalance | 641 | 2633 | 2641 | 2641 | 6036 | +| feeBps | 338 | 338 | 338 | 338 | 37 | +| feeTo | 383 | 2278 | 2383 | 2383 | 344 | +| feesEnabled | 350 | 1016 | 350 | 2350 | 3 | +| newOptionType | 3527 | 47960 | 9148 | 106071 | 294 | +| option | 1978 | 3231 | 1978 | 9978 | 7 | +| position | 1272 | 6147 | 6354 | 14038 | 38 | +| redeem | 465 | 14783 | 15492 | 29378 | 44 | +| safeTransferFrom | 3522 | 16945 | 19442 | 28802 | 79 | +| setFeeTo | 720 | 1837 | 720 | 24712 | 84 | +| setFeesEnabled | 1690 | 2581 | 2687 | 6912 | 351 | +| setTokenURIGenerator | 2638 | 4715 | 2733 | 8775 | 3 | +| sweepFees | 2885 | 16380 | 15798 | 83958 | 253 | +| tokenType | 724 | 1647 | 1062 | 2724 | 5 | +| tokenURIGenerator | 426 | 1426 | 1426 | 2426 | 2 | +| uri | 9574 | 236923 | 236923 | 464273 | 2 | +| write | 450 | 125068 | 115360 | 242841 | 432 | +| test/ValoremOptionsClearinghouse.invariant.t.sol:ValoremOptionsClearinghouseInvariantTest contract | | | | | | +|----------------------------------------------------------------------------------------------------|-----------------|--------|--------|--------|---------| +| Deployment Cost | Deployment Size | | | | | +| 10565393 | 52415 | | | | | +| Function Name | min | avg | median | max | # calls | +| addOptionType | 27437 | 29091 | 27437 | 44537 | 31 | +| getClaimIds | 2672 | 2672 | 2672 | 2672 | 393 | +| getMockErc20s | 16409 | 16409 | 16409 | 16409 | 432 | +| getOptionTypes | 2717 | 12650 | 11727 | 31844 | 1125 | +| invariant_erc20_balances | 208393 | 208393 | 208393 | 208393 | 1000 | +| invariant_options_written_match_claims | 2299 | 64271 | 73068 | 122875 | 1000 | +| invariant_positions_accounting | 91974 | 91974 | 91974 | 91974 | 1000 | +| test/actors/OptionHolder.sol:OptionHolder contract | | | | | | +|----------------------------------------------------|-----------------|-------|--------|-------|---------| +| Deployment Cost | Deployment Size | | | | | +| 277087 | 1418 | | | | | +| Function Name | min | avg | median | max | # calls | +| exercise | 11320 | 27637 | 28575 | 49432 | 771 | +| test/actors/OptionWriter.sol:OptionWriter contract | | | | | | +|----------------------------------------------------|-----------------|--------|--------|--------|---------| +| Deployment Cost | Deployment Size | | | | | +| 756371 | 3769 | | | | | +| Function Name | min | avg | median | max | # calls | +| newOptionType | 35797 | 59160 | 36220 | 183385 | 186 | +| redeem | 11386 | 11386 | 11386 | 11386 | 201 | +| writeExisting | 16468 | 119726 | 97608 | 294042 | 192 | +| writeNew | 12278 | 123111 | 102700 | 289864 | 162 | +| test/actors/ProtocolAdmin.sol:ProtocolAdmin contract | | | | | | +|------------------------------------------------------|-----------------|-------|--------|-------|---------| +| Deployment Cost | Deployment Size | | | | | +| 546910 | 2818 | | | | | +| Function Name | min | avg | median | max | # calls | +| setFeeTo | 3552 | 6301 | 3552 | 12223 | 246 | +| setFeesEnabled | 11067 | 11067 | 11067 | 11067 | 261 | +| sweepFees | 55260 | 55260 | 55260 | 55260 | 246 | +| test/actors/Timekeeper.sol:Timekeeper contract | | | | | | +|------------------------------------------------|-----------------|------|--------|------|---------| +| Deployment Cost | Deployment Size | | | | | +| 96747 | 515 | | | | | +| Function Name | min | avg | median | max | # calls | +| tickTock | 3754 | 3754 | 3754 | 3754 | 735 | +| test/utils/MockERC20.sol:MockERC20 contract | | | | | | +|---------------------------------------------|-----------------|-------|--------|-------|---------| +| Deployment Cost | Deployment Size | | | | | +| 648998 | 4360 | | | | | +| Function Name | min | avg | median | max | # calls | +| approve | 2546 | 24529 | 24546 | 24546 | 2616 | +| balanceOf | 542 | 2536 | 2542 | 2542 | 54182 | +| decimals | 249 | 249 | 249 | 249 | 2 | +| mint | 2896 | 31899 | 24796 | 46696 | 2616 | +| symbol | 3236 | 3236 | 3236 | 3236 | 2 | +| totalSupply | 363 | 2305 | 2363 | 2363 | 6311 | +| transfer | 2985 | 4962 | 2985 | 24885 | 146 | +| transferFrom | 824 | 16066 | 5030 | 32081 | 351 | From 79517e99b01f6ceb6b1c70875f643ece5aedb247 Mon Sep 17 00:00:00 2001 From: neodaoist Date: Tue, 19 Sep 2023 16:47:23 +0300 Subject: [PATCH 13/14] chore: simplify format --- .gas-snapshot-custom | 60 -------------------------------------------- 1 file changed, 60 deletions(-) diff --git a/.gas-snapshot-custom b/.gas-snapshot-custom index ae37902..be2cbba 100644 --- a/.gas-snapshot-custom +++ b/.gas-snapshot-custom @@ -1,9 +1,3 @@ -| src/TokenURIGenerator.sol:TokenURIGenerator contract | | | | | | -|------------------------------------------------------|-----------------|--------|--------|--------|---------| -| Deployment Cost | Deployment Size | | | | | -| 1982298 | 9933 | | | | | -| Function Name | min | avg | median | max | # calls | -| constructTokenURI | 420115 | 420115 | 420115 | 420115 | 1 | | src/ValoremOptionsClearinghouse.sol:ValoremOptionsClearinghouse contract | | | | | | |--------------------------------------------------------------------------|-----------------|--------|--------|--------|---------| | Deployment Cost | Deployment Size | | | | | @@ -30,57 +24,3 @@ | tokenURIGenerator | 426 | 1426 | 1426 | 2426 | 2 | | uri | 9574 | 236923 | 236923 | 464273 | 2 | | write | 450 | 125068 | 115360 | 242841 | 432 | -| test/ValoremOptionsClearinghouse.invariant.t.sol:ValoremOptionsClearinghouseInvariantTest contract | | | | | | -|----------------------------------------------------------------------------------------------------|-----------------|--------|--------|--------|---------| -| Deployment Cost | Deployment Size | | | | | -| 10565393 | 52415 | | | | | -| Function Name | min | avg | median | max | # calls | -| addOptionType | 27437 | 29091 | 27437 | 44537 | 31 | -| getClaimIds | 2672 | 2672 | 2672 | 2672 | 393 | -| getMockErc20s | 16409 | 16409 | 16409 | 16409 | 432 | -| getOptionTypes | 2717 | 12650 | 11727 | 31844 | 1125 | -| invariant_erc20_balances | 208393 | 208393 | 208393 | 208393 | 1000 | -| invariant_options_written_match_claims | 2299 | 64271 | 73068 | 122875 | 1000 | -| invariant_positions_accounting | 91974 | 91974 | 91974 | 91974 | 1000 | -| test/actors/OptionHolder.sol:OptionHolder contract | | | | | | -|----------------------------------------------------|-----------------|-------|--------|-------|---------| -| Deployment Cost | Deployment Size | | | | | -| 277087 | 1418 | | | | | -| Function Name | min | avg | median | max | # calls | -| exercise | 11320 | 27637 | 28575 | 49432 | 771 | -| test/actors/OptionWriter.sol:OptionWriter contract | | | | | | -|----------------------------------------------------|-----------------|--------|--------|--------|---------| -| Deployment Cost | Deployment Size | | | | | -| 756371 | 3769 | | | | | -| Function Name | min | avg | median | max | # calls | -| newOptionType | 35797 | 59160 | 36220 | 183385 | 186 | -| redeem | 11386 | 11386 | 11386 | 11386 | 201 | -| writeExisting | 16468 | 119726 | 97608 | 294042 | 192 | -| writeNew | 12278 | 123111 | 102700 | 289864 | 162 | -| test/actors/ProtocolAdmin.sol:ProtocolAdmin contract | | | | | | -|------------------------------------------------------|-----------------|-------|--------|-------|---------| -| Deployment Cost | Deployment Size | | | | | -| 546910 | 2818 | | | | | -| Function Name | min | avg | median | max | # calls | -| setFeeTo | 3552 | 6301 | 3552 | 12223 | 246 | -| setFeesEnabled | 11067 | 11067 | 11067 | 11067 | 261 | -| sweepFees | 55260 | 55260 | 55260 | 55260 | 246 | -| test/actors/Timekeeper.sol:Timekeeper contract | | | | | | -|------------------------------------------------|-----------------|------|--------|------|---------| -| Deployment Cost | Deployment Size | | | | | -| 96747 | 515 | | | | | -| Function Name | min | avg | median | max | # calls | -| tickTock | 3754 | 3754 | 3754 | 3754 | 735 | -| test/utils/MockERC20.sol:MockERC20 contract | | | | | | -|---------------------------------------------|-----------------|-------|--------|-------|---------| -| Deployment Cost | Deployment Size | | | | | -| 648998 | 4360 | | | | | -| Function Name | min | avg | median | max | # calls | -| approve | 2546 | 24529 | 24546 | 24546 | 2616 | -| balanceOf | 542 | 2536 | 2542 | 2542 | 54182 | -| decimals | 249 | 249 | 249 | 249 | 2 | -| mint | 2896 | 31899 | 24796 | 46696 | 2616 | -| symbol | 3236 | 3236 | 3236 | 3236 | 2 | -| totalSupply | 363 | 2305 | 2363 | 2363 | 6311 | -| transfer | 2985 | 4962 | 2985 | 24885 | 146 | -| transferFrom | 824 | 16066 | 5030 | 32081 | 351 | From 32e6dd15e169c78cb11e5613052737a3a2be840c Mon Sep 17 00:00:00 2001 From: neodaoist Date: Tue, 19 Sep 2023 16:50:27 +0300 Subject: [PATCH 14/14] chore: test formatting --- .gas-snapshot-custom | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gas-snapshot-custom b/.gas-snapshot-custom index be2cbba..e7228b5 100644 --- a/.gas-snapshot-custom +++ b/.gas-snapshot-custom @@ -11,6 +11,8 @@ | feeBps | 338 | 338 | 338 | 338 | 37 | | feeTo | 383 | 2278 | 2383 | 2383 | 344 | | feesEnabled | 350 | 1016 | 350 | 2350 | 3 | +| net | x | x | x | x | x | +| nettable | x | x | x | x | x | | newOptionType | 3527 | 47960 | 9148 | 106071 | 294 | | option | 1978 | 3231 | 1978 | 9978 | 7 | | position | 1272 | 6147 | 6354 | 14038 | 38 |