Skip to content

Commit

Permalink
Gas optimizations in storage structs
Browse files Browse the repository at this point in the history
  • Loading branch information
0xAlcibiades authored Mar 25, 2022
1 parent f634675 commit e260cbf
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 46 deletions.
12 changes: 12 additions & 0 deletions .gas-snapshot
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
OptionSettlementTest:testExercise() (gas: 182892)
OptionSettlementTest:testFailDuplicateChain() (gas: 13642)
OptionSettlementTest:testFailExercise(uint112,uint112) (runs: 256, μ: 88228, ~: 111289)
OptionSettlementTest:testFailUri() (gas: 7693)
OptionSettlementTest:testFuzzExercise(uint112,uint112) (runs: 256, μ: 210415, ~: 217421)
OptionSettlementTest:testFuzzNewChain(uint160,uint96,uint96,uint40,uint40) (runs: 256, μ: 159428, ~: 159428)
OptionSettlementTest:testFuzzRedeem(uint112) (runs: 256, μ: 146653, ~: 146655)
OptionSettlementTest:testFuzzWrite(uint112) (runs: 256, μ: 174449, ~: 174449)
OptionSettlementTest:testNewChain() (gas: 148239)
OptionSettlementTest:testRedeem() (gas: 134716)
OptionSettlementTest:testUri() (gas: 10245)
OptionSettlementTest:testWrite() (gas: 170342)
22 changes: 11 additions & 11 deletions src/OptionSettlement.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,27 +31,27 @@ struct Option {
// The underlying asset to be received
address underlyingAsset;
// The timestamp after which this option may be exercised
uint64 exerciseTimestamp;
uint40 exerciseTimestamp;
// The timestamp before which this option must be exercised
uint40 expiryTimestamp;
// The address of the asset needed for exercise
address exerciseAsset;
// The timestamp before which this option must be exercised
uint64 expiryTimestamp;
// Random seed created at the time of option chain creation
uint256 settlementSeed;
// The amount of the underlying asset contained within an option contract of this type
uint256 underlyingAmount;
uint96 underlyingAmount;
// Random seed created at the time of option chain creation
uint160 settlementSeed;
// The amount of the exercise asset required to exercise this option
uint256 exerciseAmount;
uint96 exerciseAmount;
}

struct Claim {
// Which option was written
uint256 option;
// These are 1:1 contracts with the underlying Option struct
// The number of contracts written in this claim
uint256 amountWritten;
uint112 amountWritten;
// The amount of contracts assigned for exercise to this claim
uint256 amountExercised;
uint112 amountExercised;
// The two amounts above along with the option info, can be used to calculate the underlying assets
bool claimed;
}
Expand Down Expand Up @@ -161,7 +161,7 @@ contract OptionSettlementEngine is ERC1155 {
chainMap[chainKey] = true;
}

function write(uint256 optionId, uint256 amount) external {
function write(uint256 optionId, uint112 amount) external {
require(tokenType[optionId] == Type.Option, "Token is not an option");
require(
option[optionId].settlementSeed != 0,
Expand Down Expand Up @@ -199,7 +199,7 @@ contract OptionSettlementEngine is ERC1155 {
tokens[1] = claimId;

uint256[] memory amounts = new uint256[](2);
amounts[0] = amount;
amounts[0] = uint256(amount);
amounts[1] = 1;

bytes memory data = new bytes(0);
Expand Down
70 changes: 35 additions & 35 deletions src/test/OptionSettlement.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@ contract OptionSettlementTest is DSTest, NFTreceiver {
Option memory info = Option({
underlyingAsset: address(weth),
exerciseAsset: address(dai),
settlementSeed: 1,
underlyingAmount: 1 ether,
exerciseAmount: 3000 ether,
exerciseTimestamp: uint64(block.timestamp),
expiryTimestamp: (uint64(block.timestamp) + 604800)
settlementSeed: uint160(1),
underlyingAmount: uint96(1 ether),
exerciseAmount: uint96(3000 ether),
exerciseTimestamp: uint40(block.timestamp),
expiryTimestamp: (uint40(block.timestamp) + 604800)
});
engine.newChain(info);

Expand All @@ -106,31 +106,31 @@ contract OptionSettlementTest is DSTest, NFTreceiver {
Option memory info = Option({
underlyingAsset: address(weth),
exerciseAsset: address(dai),
settlementSeed: 0,
underlyingAmount: 1 ether,
exerciseAmount: 3100 ether,
exerciseTimestamp: uint64(block.timestamp),
expiryTimestamp: (uint64(block.timestamp) + 604800)
settlementSeed: uint160(1),
underlyingAmount: uint96(1 ether),
exerciseAmount: uint96(3100 ether),
exerciseTimestamp: uint40(block.timestamp),
expiryTimestamp: (uint40(block.timestamp) + 604800)
});

uint256 tokenId = engine.newChain(info);

(
,
uint64 testExerciseTimestamp,
uint40 testExerciseTimestamp,
uint40 testExpiryTimestamp,
,
uint64 testExpiryTimestamp,
uint256 testSettlementSeed,
uint256 testUnderlyingAmount,
uint256 testExerciseAmount
uint96 testUnderlyingAmount,
uint160 testSettlementSeed,
uint96 testExerciseAmount
) = engine.option(nextTokenId);

assertTrue(engine.chainMap(keccak256(abi.encode(info))));
assertEq(engine.nextTokenId(), nextTokenId + 1);
assertEq(tokenId, engine.nextTokenId() - 1);

assertEq(testExerciseTimestamp, uint64(block.timestamp));
assertEq(testExpiryTimestamp, (uint64(block.timestamp) + 604800));
assertEq(testExerciseTimestamp, uint40(block.timestamp));
assertEq(testExpiryTimestamp, (uint40(block.timestamp) + 604800));
assertEq(testUnderlyingAmount, 1 ether);
assertEq(testExerciseAmount, 3100 ether);
assertEq(testSettlementSeed, 42);
Expand All @@ -140,19 +140,19 @@ contract OptionSettlementTest is DSTest, NFTreceiver {
}

function testFuzzNewChain(
uint256 settlementSeed,
uint256 underlyingAmount,
uint256 exerciseAmount,
uint64 exerciseTimestamp,
uint64 expiryTimestamp
uint160 settlementSeed,
uint96 underlyingAmount,
uint96 exerciseAmount,
uint40 exerciseTimestamp,
uint40 expiryTimestamp
) public {
uint256 nextTokenId = engine.nextTokenId();

VM.assume(expiryTimestamp >= block.timestamp + 86400);
VM.assume(exerciseTimestamp >= block.timestamp);
VM.assume(exerciseTimestamp <= expiryTimestamp - 86400);
VM.assume(expiryTimestamp <= type(uint64).max);
VM.assume(exerciseTimestamp <= type(uint64).max);
VM.assume(expiryTimestamp <= type(uint40).max);
VM.assume(exerciseTimestamp <= type(uint40).max);
VM.assume(underlyingAmount <= wethTotalSupply);
VM.assume(exerciseAmount <= daiTotalSupply);
VM.assume(type(uint256).max - underlyingAmount >= wethTotalSupply);
Expand All @@ -172,12 +172,12 @@ contract OptionSettlementTest is DSTest, NFTreceiver {

(
,
uint64 testExerciseTimestamp,
uint40 testExerciseTimestamp,
uint40 testExpiryTimestamp,
,
uint64 testExpiryTimestamp,
uint256 testSettlementSeed,
uint256 testUnderlyingAmount,
uint256 testExerciseAmount
uint96 testUnderlyingAmount,
uint160 testSettlementSeed,
uint96 testExerciseAmount
) = engine.option(nextTokenId);

assertTrue(engine.chainMap(keccak256(abi.encode(info))));
Expand All @@ -202,8 +202,8 @@ contract OptionSettlementTest is DSTest, NFTreceiver {
settlementSeed: 1,
underlyingAmount: 1 ether,
exerciseAmount: 3000 ether,
exerciseTimestamp: uint64(block.timestamp),
expiryTimestamp: (uint64(block.timestamp) + 604800)
exerciseTimestamp: uint40(block.timestamp),
expiryTimestamp: (uint40(block.timestamp) + 604800)
});
engine.newChain(info);
}
Expand Down Expand Up @@ -259,7 +259,7 @@ contract OptionSettlementTest is DSTest, NFTreceiver {
assertTrue(true);
}

function testFuzzWrite(uint256 amountWrite) public {
function testFuzzWrite(uint112 amountWrite) public {
uint256 nextTokenId = engine.nextTokenId();
uint256 wethBalanceEngine = IERC20(weth).balanceOf(address(engine));
uint256 wethFeeTo = IERC20(weth).balanceOf(address(engine.feeTo()));
Expand Down Expand Up @@ -345,7 +345,7 @@ contract OptionSettlementTest is DSTest, NFTreceiver {
assertEq(engine.balanceOf(address(this), 1), 1);
}

function testFuzzExercise(uint256 amountWrite, uint256 amountExercise)
function testFuzzExercise(uint112 amountWrite, uint112 amountExercise)
public
{
// TODO(add checks after updating exercise())
Expand Down Expand Up @@ -405,7 +405,7 @@ contract OptionSettlementTest is DSTest, NFTreceiver {
assertEq(engine.balanceOf(address(this), 1), 1);
}

function testFailExercise(uint256 amountWrite, uint256 amountExercise)
function testFailExercise(uint112 amountWrite, uint112 amountExercise)
public
{
VM.assume(amountExercise > amountWrite);
Expand Down Expand Up @@ -441,7 +441,7 @@ contract OptionSettlementTest is DSTest, NFTreceiver {
if (engine.tokenType(1) == Type.None) assertTrue(true);
}

function testFuzzRedeem(uint256 amountWrite) public {
function testFuzzRedeem(uint112 amountWrite) public {
// TODO(add checks after updating exercise())
uint256 wethBalanceEngine = IERC20(weth).balanceOf(address(engine));
uint256 daiBalanceEngine = IERC20(dai).balanceOf(address(engine));
Expand Down

0 comments on commit e260cbf

Please sign in to comment.