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

fix tests with removing bucket accessor #105

Merged
merged 3 commits into from
Nov 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 0 additions & 16 deletions src/OptionSettlementEngine.sol
Original file line number Diff line number Diff line change
Expand Up @@ -143,22 +143,6 @@ contract OptionSettlementEngine is ERC1155, IOptionSettlementEngine {
return _option[optionKey].underlyingAsset != address(0x0);
}

// TODO remove
/**
* @notice Returns the total amount of options written and exercised for all
* option lot claims created on the supplied index.
* @param optionId The id of the option for the claim buckets.
* @param dayBucket The index of the claimBucket to return.
*/
function claimBucket(uint256 optionId, uint16 dayBucket)
external
view
returns (OptionLotClaimBucket memory claimBucketInfo)
{
(uint160 optionKey,) = decodeTokenId(optionId);
claimBucketInfo = _claimBucketByOption[optionKey][dayBucket];
}

/*//////////////////////////////////////////////////////////////
// Token URI
//////////////////////////////////////////////////////////////*/
Expand Down
111 changes: 40 additions & 71 deletions test/OptionSettlement.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ contract OptionSettlementTest is Test, NFTreceiver {
assertEq(false, claimRecord.claimed);
}

function testFailAssignMultipleBuckets() public {
function testAssignMultipleBuckets() public {
// New option type with expiry in 5d
testExerciseTimestamp = uint40(block.timestamp + 1 days);
testExpiryTimestamp = uint40(block.timestamp + 5 * 1 days);
Expand Down Expand Up @@ -396,37 +396,42 @@ contract OptionSettlementTest is Test, NFTreceiver {
// randomly seeded based on option type seed. asserts will fail if seed
// algo changes.
// first lot is completely un exercised
assertEq(engine.underlying(claimId1).exercisePosition, 0);
_assertAssignedInBucket(optionId, 0, 0);
_assertAssignedInBucket(optionId, 1, 70);
emit log_named_int("claimId1 exercise", engine.underlying(claimId1).exercisePosition);
emit log_named_int("claimId1 underlying", engine.underlying(claimId1).underlyingPosition);

_assertClaimAmountExercised(claimId1, 69);
_assertClaimAmountExercised(claimId2, 1);

// Jump ahead to option expiry
vm.warp(1 + option.expiryTimestamp);
vm.startPrank(ALICE);
uint256 aliceBalanceExerciseAsset = ERC20(option.exerciseAsset).balanceOf(ALICE);
uint256 aliceBalanceUnderlyingAsset = ERC20(option.underlyingAsset).balanceOf(ALICE);
// Alice's first claim should be completely unexercised
// Alice's first claim should be completely exercised
engine.redeem(claimId1);
assertEq(aliceBalanceExerciseAsset, ERC20(option.exerciseAsset).balanceOf(ALICE));
assertEq(ERC20(option.exerciseAsset).balanceOf(ALICE), aliceBalanceExerciseAsset + 69 * option.exerciseAmount);
assertEq(aliceBalanceUnderlyingAsset, ERC20(option.underlyingAsset).balanceOf(ALICE));

aliceBalanceExerciseAsset = ERC20(option.exerciseAsset).balanceOf(ALICE);
aliceBalanceUnderlyingAsset = ERC20(option.underlyingAsset).balanceOf(ALICE);

// BOB exercised 70 options
// ALICE should retrieve 70 * exerciseAmount of the exercise asset
// ALICE should retrieve (100-70) * underlyingAmount of the underlying asset
engine.redeem(claimId2);
assertEq(ERC20(option.exerciseAsset).balanceOf(ALICE), aliceBalanceExerciseAsset + 70 * option.exerciseAmount);
assertEq(ERC20(option.exerciseAsset).balanceOf(ALICE), aliceBalanceExerciseAsset + 1 * option.exerciseAmount);
assertEq(
ERC20(option.underlyingAsset).balanceOf(ALICE), aliceBalanceUnderlyingAsset + 30 * option.underlyingAmount
ERC20(option.underlyingAsset).balanceOf(ALICE), aliceBalanceUnderlyingAsset + 99 * option.underlyingAmount
);
}

function testFailRandomAssignment() public {
function testRandomAssignment() public {
uint16 numDays = 7;
uint256[] memory claimIds = new uint256[](numDays);
// New option type with expiry in 1w
testExerciseTimestamp = uint40(block.timestamp - 1);
testExpiryTimestamp = uint40(block.timestamp + numDays * 1 days + 1);
(uint256 optionId, IOptionSettlementEngine.Option memory optionInfo) = _createNewOptionType({
(uint256 optionId,) = _createNewOptionType({
underlyingAsset: WETH_A,
underlyingAmount: testUnderlyingAmount + 1, // to mess w seed
exerciseAsset: DAI_A,
Expand All @@ -436,48 +441,46 @@ contract OptionSettlementTest is Test, NFTreceiver {
});

vm.startPrank(ALICE);
uint256 claimId = engine.write(optionId, 1);
for (uint256 i = 1; i < numDays; i++) {
for (uint256 i = 0; i < numDays; i++) {
// write a single option
uint256 claimId = engine.write(optionId, 1);
claimIds[i] = claimId;
vm.warp(block.timestamp + 1 days);
// write a single option, adding it to the same lot
engine.write(optionId, 1, claimId);
}
engine.safeTransferFrom(ALICE, BOB, optionId, numDays, "");
vm.stopPrank();

_emitBuckets(optionId, optionInfo);

vm.startPrank(BOB);

// assign a single option on day 2
engine.exercise(optionId, 1);
_assertAssignedInBucket(optionId, 0, 0);
_assertAssignedInBucket(optionId, 1, 0);
_assertAssignedInBucket(optionId, 2, 1);
_assertAssignedInBucket(optionId, 3, 0);
_assertAssignedInBucket(optionId, 4, 0);
_assertAssignedInBucket(optionId, 5, 0);
_assertAssignedInBucket(optionId, 6, 0);
_assertClaimAmountExercised(claimIds[0], 0);
_assertClaimAmountExercised(claimIds[1], 0);
_assertClaimAmountExercised(claimIds[2], 0);
_assertClaimAmountExercised(claimIds[3], 1);
_assertClaimAmountExercised(claimIds[4], 0);
_assertClaimAmountExercised(claimIds[5], 0);
_assertClaimAmountExercised(claimIds[6], 0);

// assigns a single option on day 4
engine.exercise(optionId, 1);
_assertAssignedInBucket(optionId, 0, 0);
_assertAssignedInBucket(optionId, 1, 0);
_assertAssignedInBucket(optionId, 2, 1);
_assertAssignedInBucket(optionId, 3, 0);
_assertAssignedInBucket(optionId, 4, 1);
_assertAssignedInBucket(optionId, 5, 0);
_assertAssignedInBucket(optionId, 6, 0);
_assertClaimAmountExercised(claimIds[0], 0);
_assertClaimAmountExercised(claimIds[1], 0);
_assertClaimAmountExercised(claimIds[2], 0);
_assertClaimAmountExercised(claimIds[3], 1);
_assertClaimAmountExercised(claimIds[4], 1);
_assertClaimAmountExercised(claimIds[5], 0);
_assertClaimAmountExercised(claimIds[6], 0);

// assigns a single option on day 1
engine.exercise(optionId, 1);
_assertAssignedInBucket(optionId, 0, 0);
_assertAssignedInBucket(optionId, 1, 1);
_assertAssignedInBucket(optionId, 2, 1);
_assertAssignedInBucket(optionId, 3, 0);
_assertAssignedInBucket(optionId, 4, 1);
_assertAssignedInBucket(optionId, 5, 0);
_assertAssignedInBucket(optionId, 6, 0);
_assertClaimAmountExercised(claimIds[0], 0);
_assertClaimAmountExercised(claimIds[1], 1);
_assertClaimAmountExercised(claimIds[2], 0);
_assertClaimAmountExercised(claimIds[3], 1);
_assertClaimAmountExercised(claimIds[4], 1);
_assertClaimAmountExercised(claimIds[5], 0);
_assertClaimAmountExercised(claimIds[6], 0);
}

// **********************************************************************
Expand Down Expand Up @@ -1672,40 +1675,6 @@ contract OptionSettlementTest is Test, NFTreceiver {
return uint16((ts + daysFrom * 1 days) / 1 days);
}

function _emitBuckets(uint256 optionId, IOptionSettlementEngine.Option memory optionInfo) internal {
uint16 daysRange = uint16(optionInfo.expiryTimestamp / 1 days);

for (uint16 i = 0; i < daysRange; i++) {
IOptionSettlementEngine.OptionLotClaimBucket memory bucket;
try engine.claimBucket(optionId, i) returns (IOptionSettlementEngine.OptionLotClaimBucket memory _bucket) {
bucket = _bucket;
} catch {
return;
}
emit log_named_uint("optionId:", optionId);
emit log_named_uint("index:", i);
_emitBucket(bucket);
}
}

function _emitBucket(IOptionSettlementEngine.OptionLotClaimBucket memory bucket) internal {
emit log_named_uint("bucket amount exercised", bucket.amountExercised);
emit log_named_uint("bucket amount written", bucket.amountWritten);
emit log_named_uint("bucket daysAfterEpoch", bucket.daysAfterEpoch);
}

function _assertAssignedInBucket(uint256 optionId, uint16 bucketIndex, uint112 assignedAmount) internal {
IOptionSettlementEngine.OptionLotClaimBucket memory bucket;
try engine.claimBucket(optionId, bucketIndex) returns (
IOptionSettlementEngine.OptionLotClaimBucket memory _bucket
) {
bucket = _bucket;
} catch {
return;
}
assertEq(bucket.amountExercised, assignedAmount);
}

/// @dev probability in bips
function _coinflip(uint32 seed, uint16 probability) internal pure returns (bool) {
return _randBetween(seed, 10000) < probability;
Expand Down