From f903272d6d850340f800e9c958286b6e77d044d6 Mon Sep 17 00:00:00 2001 From: neodaoist Date: Fri, 18 Nov 2022 10:00:46 -0500 Subject: [PATCH 01/16] Update forge-std --- lib/forge-std | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/forge-std b/lib/forge-std index 2a2ce36..7512977 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit 2a2ce3692b8c1523b29de3ec9d961ee9fbbc43a6 +Subproject commit 75129776235fe6ebf075b0c8d0fe412092a1ac96 From 251d2b3f037b5ddce5450db504401b111aee062f Mon Sep 17 00:00:00 2001 From: neodaoist Date: Fri, 18 Nov 2022 10:02:02 -0500 Subject: [PATCH 02/16] Simplify IERC20 usage in tests --- .gas-snapshot | 74 +++++++++++++++++------------------ test/OptionSettlement.t.sol | 2 +- test/interfaces/IERC20.sol | 77 ------------------------------------- 3 files changed, 38 insertions(+), 115 deletions(-) delete mode 100644 test/interfaces/IERC20.sol diff --git a/.gas-snapshot b/.gas-snapshot index 2939440..3e1bb7e 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,57 +1,57 @@ OptionSettlementTest:testAddOptionsToExistingClaim() (gas: 452610) -OptionSettlementTest:testAssignMultipleBuckets() (gas: 719761) -OptionSettlementTest:testDecodeTokenId() (gas: 487556) -OptionSettlementTest:testEncodeTokenId() (gas: 487157) -OptionSettlementTest:testEventExercise() (gas: 340861) -OptionSettlementTest:testEventNewOptionType() (gas: 124329) -OptionSettlementTest:testEventRedeem() (gas: 299435) -OptionSettlementTest:testEventSweepFeesWhenFeesAccruedForExercise() (gas: 1206747) -OptionSettlementTest:testEventSweepFeesWhenFeesAccruedForWrite() (gas: 1176035) -OptionSettlementTest:testEventWriteWhenExistingClaim() (gas: 322145) -OptionSettlementTest:testEventWriteWhenNewClaim() (gas: 300745) +OptionSettlementTest:testAssignMultipleBuckets() (gas: 719672) +OptionSettlementTest:testDecodeTokenId() (gas: 487578) +OptionSettlementTest:testEncodeTokenId() (gas: 487179) +OptionSettlementTest:testEventExercise() (gas: 340883) +OptionSettlementTest:testEventNewOptionType() (gas: 124313) +OptionSettlementTest:testEventRedeem() (gas: 299432) +OptionSettlementTest:testEventWriteWhenExistingClaim() (gas: 322142) +OptionSettlementTest:testEventWriteWhenNewClaim() (gas: 300742) OptionSettlementTest:testExerciseBeforeExpiry() (gas: 333471) OptionSettlementTest:testExerciseIncompleteExercise() (gas: 354573) -OptionSettlementTest:testExerciseMultipleWriteSameChain() (gas: 467359) +OptionSettlementTest:testExerciseMultipleWriteSameChain() (gas: 467337) OptionSettlementTest:testExerciseWithDifferentDecimals() (gas: 407125) -OptionSettlementTest:testFuzzDecodeTokenId(uint256,uint256) (runs: 256, μ: 10888, ~: 10888) -OptionSettlementTest:testFuzzEncodeTokenId(uint256,uint256) (runs: 256, μ: 10792, ~: 10792) -OptionSettlementTest:testFuzzExercise(uint112,uint112) (runs: 256, μ: 402721, ~: 406091) -OptionSettlementTest:testFuzzNewOptionType(uint96,uint96,uint40,uint40) (runs: 256, μ: 124635, ~: 124635) -OptionSettlementTest:testFuzzRedeem(uint112,uint112) (runs: 256, μ: 393511, ~: 397095) -OptionSettlementTest:testFuzzWrite(uint112) (runs: 256, μ: 318417, ~: 318417) -OptionSettlementTest:testFuzzWriteExerciseRedeem(uint32) (runs: 256, μ: 11619195, ~: 11689637) -OptionSettlementTest:testGetClaimForTokenId() (gas: 377636) +OptionSettlementTest:testFuzzDecodeTokenId(uint256,uint256) (runs: 256, μ: 11006, ~: 11093) +OptionSettlementTest:testFuzzEncodeTokenId(uint256,uint256) (runs: 256, μ: 10977, ~: 11064) +OptionSettlementTest:testFuzzExercise(uint112,uint112) (runs: 256, μ: 402548, ~: 406142) +OptionSettlementTest:testFuzzNewOptionType(uint96,uint96,uint40,uint40) (runs: 256, μ: 124682, ~: 124682) +OptionSettlementTest:testFuzzRedeem(uint112,uint112) (runs: 256, μ: 393324, ~: 397146) +OptionSettlementTest:testFuzzWrite(uint112) (runs: 256, μ: 318433, ~: 318433) +OptionSettlementTest:testFuzzWriteExerciseRedeem(uint32) (runs: 256, μ: 11515009, ~: 11689637) +OptionSettlementTest:testGetClaimForTokenId() (gas: 377614) OptionSettlementTest:testGetOptionForTokenId() (gas: 124586) -OptionSettlementTest:testInitial() (gas: 7824) +OptionSettlementTest:testInitial() (gas: 7857) OptionSettlementTest:testIsOptionInitialized() (gas: 124898) -OptionSettlementTest:testRandomAssignment() (gas: 1599911) -OptionSettlementTest:testRedeemNotExercised() (gas: 303070) +OptionSettlementTest:testRandomAssignment() (gas: 1600049) +OptionSettlementTest:testRedeemNotExercised() (gas: 302981) OptionSettlementTest:testRevertExerciseBeforeExcercise() (gas: 401610) OptionSettlementTest:testRevertExerciseWhenCallerHoldsInsufficientOptions() (gas: 306357) -OptionSettlementTest:testRevertExerciseWhenExerciseTooEarly() (gas: 308047) +OptionSettlementTest:testRevertExerciseWhenExerciseTooEarly() (gas: 308069) OptionSettlementTest:testRevertExerciseWhenExpiredOption() (gas: 427786) OptionSettlementTest:testRevertExerciseWhenInvalidOption() (gas: 294521) -OptionSettlementTest:testRevertNewOptionTypeWhenExerciseWindowTooShort() (gas: 19289) +OptionSettlementTest:testRevertNewOptionTypeWhenExerciseWindowTooShort() (gas: 19333) OptionSettlementTest:testRevertNewOptionTypeWhenExpiryTooSoon() (gas: 20674) OptionSettlementTest:testRevertNewOptionTypeWhenInvalidAssets() (gas: 20879) -OptionSettlementTest:testRevertNewOptionTypeWhenOptionsTypeExists() (gas: 22618) -OptionSettlementTest:testRevertNewOptionTypeWhenTotalSuppliesAreTooLowToExercise() (gas: 48813) +OptionSettlementTest:testRevertNewOptionTypeWhenOptionsTypeExists() (gas: 22640) +OptionSettlementTest:testRevertNewOptionTypeWhenTotalSuppliesAreTooLowToExercise() (gas: 48835) OptionSettlementTest:testRevertRedeemWhenCallerDoesNotOwnClaimId() (gas: 318655) -OptionSettlementTest:testRevertRedeemWhenClaimTooSoon() (gas: 298679) +OptionSettlementTest:testRevertRedeemWhenClaimTooSoon() (gas: 298657) OptionSettlementTest:testRevertRedeemWhenInvalidClaim() (gas: 10603) -OptionSettlementTest:testRevertSetFeeToWhenNotCurrentFeeTo() (gas: 11786) -OptionSettlementTest:testRevertSetFeeToWhenZeroAddress() (gas: 11600) +OptionSettlementTest:testRevertSetFeeToWhenNotCurrentFeeTo() (gas: 11841) +OptionSettlementTest:testRevertSetFeeToWhenZeroAddress() (gas: 11633) OptionSettlementTest:testRevertUnderlyingWhenTokenNotFound() (gas: 11779) -OptionSettlementTest:testRevertUriWhenTokenNotFound() (gas: 18596) +OptionSettlementTest:testRevertUriWhenTokenNotFound() (gas: 18618) OptionSettlementTest:testRevertWriteExpiredOption() (gas: 16537) OptionSettlementTest:testRevertWriteWhenAmountWrittenCannotBeZero() (gas: 10881) -OptionSettlementTest:testRevertWriteWhenCallerDoesNotOwnClaimId() (gas: 302983) +OptionSettlementTest:testRevertWriteWhenCallerDoesNotOwnClaimId() (gas: 302904) OptionSettlementTest:testRevertWriteWhenEncodedOptionIdInClaimIdDoesNotMatchProvidedOptionId() (gas: 11690) OptionSettlementTest:testRevertWriteWhenExpiredOption() (gas: 295699) -OptionSettlementTest:testRevertWriteWhenInvalidOption() (gas: 13650) -OptionSettlementTest:testSetFeeTo() (gas: 15731) +OptionSettlementTest:testRevertWriteWhenInvalidOption() (gas: 13672) +OptionSettlementTest:testSetFeeTo() (gas: 15797) +OptionSettlementTest:testSweepFeesWhenFeesAccruedForExercise() (gas: 1558429) +OptionSettlementTest:testSweepFeesWhenFeesAccruedForWrite() (gas: 1555682) OptionSettlementTest:testTokenURI() (gas: 480880) -OptionSettlementTest:testUnderlyingAfterExercise() (gas: 375445) -OptionSettlementTest:testUnderlyingForFungibleOptionToken() (gas: 31064) -OptionSettlementTest:testUnderlyingWhenNotExercised() (gas: 304741) -OptionSettlementTest:testWriteMultipleWriteSameOptionType() (gas: 431129) +OptionSettlementTest:testUnderlyingAfterExercise() (gas: 375432) +OptionSettlementTest:testUnderlyingForFungibleOptionToken() (gas: 31140) +OptionSettlementTest:testUnderlyingWhenNotExercised() (gas: 304654) +OptionSettlementTest:testWriteMultipleWriteSameOptionType() (gas: 431139) diff --git a/test/OptionSettlement.t.sol b/test/OptionSettlement.t.sol index 04848c0..341caa5 100644 --- a/test/OptionSettlement.t.sol +++ b/test/OptionSettlement.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.11; import "forge-std/Test.sol"; -import "./interfaces/IERC20.sol"; +import {IERC20} from "forge-std/interfaces/IERC20.sol"; import "../src/OptionSettlementEngine.sol"; /// @notice Receiver hook utility for NFT 'safe' transfers diff --git a/test/interfaces/IERC20.sol b/test/interfaces/IERC20.sol deleted file mode 100644 index fd4c95f..0000000 --- a/test/interfaces/IERC20.sol +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.11; - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom(address from, address to, uint256 amount) external returns (bool); - - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); -} From 46b4b28630c851185b9ca49ca6d22bf75648510e Mon Sep 17 00:00:00 2001 From: neodaoist Date: Fri, 18 Nov 2022 10:07:39 -0500 Subject: [PATCH 03/16] Remove forge-std --- .gitmodules | 3 --- lib/forge-std | 1 - 2 files changed, 4 deletions(-) delete mode 160000 lib/forge-std diff --git a/.gitmodules b/.gitmodules index 70f9cbd..8e298b4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,9 +4,6 @@ [submodule "lib/solmate"] path = lib/solmate url = https://github.com/rari-capital/solmate -[submodule "lib/forge-std"] - path = lib/forge-std - url = https://github.com/brockelmore/forge-std [submodule "lib/chainlink"] path = lib/chainlink url = https://github.com/smartcontractkit/chainlink diff --git a/lib/forge-std b/lib/forge-std deleted file mode 160000 index 7512977..0000000 --- a/lib/forge-std +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 75129776235fe6ebf075b0c8d0fe412092a1ac96 From 6ab0631e02c1a30f40aeb3b437f2a3f19b85fd2a Mon Sep 17 00:00:00 2001 From: neodaoist Date: Fri, 18 Nov 2022 10:07:45 -0500 Subject: [PATCH 04/16] forge install: forge-std --- .gitmodules | 3 +++ lib/forge-std | 1 + 2 files changed, 4 insertions(+) create mode 160000 lib/forge-std diff --git a/.gitmodules b/.gitmodules index 8e298b4..e5ead23 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "lib/chainlink"] path = lib/chainlink url = https://github.com/smartcontractkit/chainlink +[submodule "lib/forge-std"] + path = lib/forge-std + url = https://github.com/foundry-rs/forge-std diff --git a/lib/forge-std b/lib/forge-std new file mode 160000 index 0000000..7512977 --- /dev/null +++ b/lib/forge-std @@ -0,0 +1 @@ +Subproject commit 75129776235fe6ebf075b0c8d0fe412092a1ac96 From 50cddf6ab5f5acbce5c4d81b275d42d9c5d90b68 Mon Sep 17 00:00:00 2001 From: neodaoist Date: Fri, 18 Nov 2022 10:12:31 -0500 Subject: [PATCH 05/16] Foundry maintenance --- .gitmodules | 3 --- foundry.toml | 1 - lib/ds-test | 1 - remappings.txt | 3 +++ 4 files changed, 3 insertions(+), 5 deletions(-) delete mode 160000 lib/ds-test create mode 100644 remappings.txt diff --git a/.gitmodules b/.gitmodules index e5ead23..2e282c7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ -[submodule "lib/ds-test"] - path = lib/ds-test - url = https://github.com/dapphub/ds-test [submodule "lib/solmate"] path = lib/solmate url = https://github.com/rari-capital/solmate diff --git a/foundry.toml b/foundry.toml index f509f89..1b11753 100644 --- a/foundry.toml +++ b/foundry.toml @@ -2,7 +2,6 @@ src = 'src' out = 'out' libs = ['lib'] -remappings = ['ds-test/=lib/ds-test/src/'] [fuzz] max_test_rejects = 100000 diff --git a/lib/ds-test b/lib/ds-test deleted file mode 160000 index 9310e87..0000000 --- a/lib/ds-test +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9310e879db8ba3ea6d5c6489a579118fd264a3f5 diff --git a/remappings.txt b/remappings.txt new file mode 100644 index 0000000..892595a --- /dev/null +++ b/remappings.txt @@ -0,0 +1,3 @@ +forge-std/=lib/forge-std/src/ +chainlink/=lib/chainlink/contracts/src/ +solmate/=lib/solmate/src/ From 4e51d78ef6c670683712df20b18a67674a40b7b7 Mon Sep 17 00:00:00 2001 From: neodaoist Date: Fri, 18 Nov 2022 10:12:54 -0500 Subject: [PATCH 06/16] Bump gitmodules --- .gitmodules | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index 2e282c7..4a77b0e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,9 @@ +[submodule "lib/forge-std"] + path = lib/forge-std + url = https://github.com/foundry-rs/forge-std [submodule "lib/solmate"] path = lib/solmate url = https://github.com/rari-capital/solmate [submodule "lib/chainlink"] path = lib/chainlink url = https://github.com/smartcontractkit/chainlink -[submodule "lib/forge-std"] - path = lib/forge-std - url = https://github.com/foundry-rs/forge-std From cd848242400c895235c5c23034cf03a5101b513b Mon Sep 17 00:00:00 2001 From: neodaoist Date: Fri, 18 Nov 2022 10:14:23 -0500 Subject: [PATCH 07/16] Remove chainlink from core --- .gitmodules | 3 --- lib/chainlink | 1 - remappings.txt | 1 - 3 files changed, 5 deletions(-) delete mode 160000 lib/chainlink diff --git a/.gitmodules b/.gitmodules index 4a77b0e..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/chainlink"] - path = lib/chainlink - url = https://github.com/smartcontractkit/chainlink diff --git a/lib/chainlink b/lib/chainlink deleted file mode 160000 index ac9fc35..0000000 --- a/lib/chainlink +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ac9fc3587261e25881126529a6a6fffd41d594ee diff --git a/remappings.txt b/remappings.txt index 892595a..b9f9ed1 100644 --- a/remappings.txt +++ b/remappings.txt @@ -1,3 +1,2 @@ forge-std/=lib/forge-std/src/ -chainlink/=lib/chainlink/contracts/src/ solmate/=lib/solmate/src/ From 930546d99a16ccbcdb0ee46c2ff8f87a7209a4bf Mon Sep 17 00:00:00 2001 From: neodaoist Date: Fri, 18 Nov 2022 10:15:43 -0500 Subject: [PATCH 08/16] Lint --- .gas-snapshot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gas-snapshot b/.gas-snapshot index 3e1bb7e..265d705 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -17,7 +17,7 @@ OptionSettlementTest:testFuzzExercise(uint112,uint112) (runs: 256, μ: 402548, ~ OptionSettlementTest:testFuzzNewOptionType(uint96,uint96,uint40,uint40) (runs: 256, μ: 124682, ~: 124682) OptionSettlementTest:testFuzzRedeem(uint112,uint112) (runs: 256, μ: 393324, ~: 397146) OptionSettlementTest:testFuzzWrite(uint112) (runs: 256, μ: 318433, ~: 318433) -OptionSettlementTest:testFuzzWriteExerciseRedeem(uint32) (runs: 256, μ: 11515009, ~: 11689637) +OptionSettlementTest:testFuzzWriteExerciseRedeem(uint32) (runs: 256, μ: 11496773, ~: 11689637) OptionSettlementTest:testGetClaimForTokenId() (gas: 377614) OptionSettlementTest:testGetOptionForTokenId() (gas: 124586) OptionSettlementTest:testInitial() (gas: 7857) From 3630896d797c91e19c6dcb4378912c29202d83f1 Mon Sep 17 00:00:00 2001 From: neodaoist Date: Fri, 18 Nov 2022 10:16:33 -0500 Subject: [PATCH 09/16] Remove poetry / python tooling --- poetry.lock | 97 -------------------------------------------------- pyproject.toml | 15 -------- 2 files changed, 112 deletions(-) delete mode 100644 poetry.lock delete mode 100644 pyproject.toml diff --git a/poetry.lock b/poetry.lock deleted file mode 100644 index 1241080..0000000 --- a/poetry.lock +++ /dev/null @@ -1,97 +0,0 @@ -[[package]] -name = "crytic-compile" -version = "0.2.2" -description = "Util to facilitate smart contracts compilation." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -pysha3 = ">=1.0.2" - -[[package]] -name = "prettytable" -version = "3.2.0" -description = "A simple Python library for easily displaying tabular data in a visually appealing ASCII table format" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -wcwidth = "*" - -[package.extras] -tests = ["pytest", "pytest-cov", "pytest-lazy-fixture"] - -[[package]] -name = "pysha3" -version = "1.0.2" -description = "SHA-3 (Keccak) for Python 2.7 - 3.5" -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "slither-analyzer" -version = "0.8.2" -description = "Slither is a Solidity static analysis framework written in Python 3." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -crytic-compile = ">=0.2.2" -prettytable = ">=0.7.2" -pysha3 = ">=1.0.2" - -[[package]] -name = "wcwidth" -version = "0.2.5" -description = "Measures the displayed width of unicode strings in a terminal" -category = "main" -optional = false -python-versions = "*" - -[metadata] -lock-version = "1.1" -python-versions = "^3.9" -content-hash = "d0ec0fcccd9da1a5a8929ed257e88488d546bab27a0f133b5baf7a2cf50195de" - -[metadata.files] -crytic-compile = [ - {file = "crytic-compile-0.2.2.tar.gz", hash = "sha256:708fd968a9d8856982838e5c56e1c7ff8e3f14d1d7eac971065395a28af4a60f"}, -] -prettytable = [ - {file = "prettytable-3.2.0-py3-none-any.whl", hash = "sha256:f6c5ec87c3ef9df5bba1d32d826c1b862ecad0344dddb6082e3562caf71fe085"}, - {file = "prettytable-3.2.0.tar.gz", hash = "sha256:ae7d96c64100543dc61662b40a28f3b03c0f94a503ed121c6fca2782c5816f81"}, -] -pysha3 = [ - {file = "pysha3-1.0.2-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:6e6a84efb7856f5d760ee55cd2b446972cb7b835676065f6c4f694913ea8f8d9"}, - {file = "pysha3-1.0.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:f9046d59b3e72aa84f6dae83a040bd1184ebd7fef4e822d38186a8158c89e3cf"}, - {file = "pysha3-1.0.2-cp27-cp27m-win32.whl", hash = "sha256:9fdd28884c5d0b4edfed269b12badfa07f1c89dbc5c9c66dd279833894a9896b"}, - {file = "pysha3-1.0.2-cp27-cp27m-win_amd64.whl", hash = "sha256:41be70b06c8775a9e4d4eeb52f2f6a3f356f17539a54eac61f43a29e42fd453d"}, - {file = "pysha3-1.0.2-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:68c3a60a39f9179b263d29e221c1bd6e01353178b14323c39cc70593c30f21c5"}, - {file = "pysha3-1.0.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:59111c08b8f34495575d12e5f2ce3bafb98bea470bc81e70c8b6df99aef0dd2f"}, - {file = "pysha3-1.0.2-cp33-cp33m-win32.whl", hash = "sha256:571a246308a7b63f15f5aa9651f99cf30f2a6acba18eddf28f1510935968b603"}, - {file = "pysha3-1.0.2-cp33-cp33m-win_amd64.whl", hash = "sha256:93abd775dac570cb9951c4e423bcb2bc6303a9d1dc0dc2b7afa2dd401d195b24"}, - {file = "pysha3-1.0.2-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:11a2ba7a2e1d9669d0052fc8fb30f5661caed5512586ecbeeaf6bf9478ab5c48"}, - {file = "pysha3-1.0.2-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:5ec8da7c5c70a53b5fa99094af3ba8d343955b212bc346a0d25f6ff75853999f"}, - {file = "pysha3-1.0.2-cp34-cp34m-win32.whl", hash = "sha256:9c778fa8b161dc9348dc5cc361e94d54aa5ff18413788f4641f6600d4893a608"}, - {file = "pysha3-1.0.2-cp34-cp34m-win_amd64.whl", hash = "sha256:fd7e66999060d079e9c0e8893e78d8017dad4f59721f6fe0be6307cd32127a07"}, - {file = "pysha3-1.0.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:827b308dc025efe9b6b7bae36c2e09ed0118a81f792d888548188e97b9bf9a3d"}, - {file = "pysha3-1.0.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:4416f16b0f1605c25f627966f76873e432971824778b369bd9ce1bb63d6566d9"}, - {file = "pysha3-1.0.2-cp35-cp35m-win32.whl", hash = "sha256:c93a2676e6588abcfaecb73eb14485c81c63b94fca2000a811a7b4fb5937b8e8"}, - {file = "pysha3-1.0.2-cp35-cp35m-win_amd64.whl", hash = "sha256:684cb01d87ed6ff466c135f1c83e7e4042d0fc668fa20619f581e6add1d38d77"}, - {file = "pysha3-1.0.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:386998ee83e313b6911327174e088021f9f2061cbfa1651b97629b761e9ef5c4"}, - {file = "pysha3-1.0.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:c7c2adcc43836223680ebdf91f1d3373543dc32747c182c8ca2e02d1b69ce030"}, - {file = "pysha3-1.0.2-cp36-cp36m-win32.whl", hash = "sha256:cd5c961b603bd2e6c2b5ef9976f3238a561c58569945d4165efb9b9383b050ef"}, - {file = "pysha3-1.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:0060a66be16665d90c432f55a0ba1f6480590cfb7d2ad389e688a399183474f0"}, - {file = "pysha3-1.0.2.tar.gz", hash = "sha256:fe988e73f2ce6d947220624f04d467faf05f1bbdbc64b0a201296bb3af92739e"}, -] -slither-analyzer = [ - {file = "slither-analyzer-0.8.2.tar.gz", hash = "sha256:efbd38e5e07b2af1c16f48fad6acf8cc94ed129ae0e3f687e8cacf950635c223"}, -] -wcwidth = [ - {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, - {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, -] diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index 13545c0..0000000 --- a/pyproject.toml +++ /dev/null @@ -1,15 +0,0 @@ -[tool.poetry] -name = "valoremoptionscontracts" -version = "0.1.0" -description = "" -authors = ["Alcibiades "] - -[tool.poetry.dependencies] -python = "^3.9" -slither-analyzer = "^0.8.2" - -[tool.poetry.dev-dependencies] - -[build-system] -requires = ["poetry-core>=1.0.0"] -build-backend = "poetry.core.masonry.api" From 9171a97f23f0322e7793fd37de198420b63e728f Mon Sep 17 00:00:00 2001 From: neodaoist Date: Fri, 18 Nov 2022 10:21:11 -0500 Subject: [PATCH 10/16] Simplify remappings --- foundry.toml | 1 + remappings.txt | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 remappings.txt diff --git a/foundry.toml b/foundry.toml index 1b11753..28f2340 100644 --- a/foundry.toml +++ b/foundry.toml @@ -2,6 +2,7 @@ src = 'src' out = 'out' libs = ['lib'] +remappings = ['forge-std/=lib/forge-std/src/', 'solmate/=lib/solmate/src/'] [fuzz] max_test_rejects = 100000 diff --git a/remappings.txt b/remappings.txt deleted file mode 100644 index b9f9ed1..0000000 --- a/remappings.txt +++ /dev/null @@ -1,2 +0,0 @@ -forge-std/=lib/forge-std/src/ -solmate/=lib/solmate/src/ From f35a6d03706d04ecf95e38c1fa582f8521a9c313 Mon Sep 17 00:00:00 2001 From: neodaoist Date: Fri, 18 Nov 2022 10:55:31 -0500 Subject: [PATCH 11/16] Small cleanups --- src/OptionSettlementEngine.sol | 17 +++++++---------- src/interfaces/IOptionSettlementEngine.sol | 8 ++++---- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/OptionSettlementEngine.sol b/src/OptionSettlementEngine.sol index 08f8558..7ee7fac 100644 --- a/src/OptionSettlementEngine.sol +++ b/src/OptionSettlementEngine.sol @@ -4,9 +4,10 @@ pragma solidity 0.8.11; import "base64/Base64.sol"; import "solmate/tokens/ERC20.sol"; import "solmate/tokens/ERC1155.sol"; -import "./interfaces/IOptionSettlementEngine.sol"; import "solmate/utils/SafeTransferLib.sol"; import "solmate/utils/FixedPointMathLib.sol"; + +import "./interfaces/IOptionSettlementEngine.sol"; import "./TokenURIGenerator.sol"; /** @@ -138,11 +139,7 @@ contract OptionSettlementEngine is ERC1155, IOptionSettlementEngine { return Type.OptionLotClaim; } - /** - * @notice Check to see if an option is already initialized - * @param optionKey The option key to check - * @return Whether or not the option is initialized - */ + /// @inheritdoc IOptionSettlementEngine function isOptionInitialized(uint160 optionKey) public view returns (bool) { return _option[optionKey].underlyingAsset != address(0x0); } @@ -458,15 +455,15 @@ contract OptionSettlementEngine is ERC1155, IOptionSettlementEngine { } /*////////////////////////////////////////////////////////////// - // Redeem Option Lot Claims + // Redeem Claims //////////////////////////////////////////////////////////////*/ + /// @inheritdoc IOptionSettlementEngine /// @dev Fair assignment is performed here. After option expiry, any claim holder /// seeking to redeem their claim for the underlying and exercise assets will claim /// amounts proportional to the per-day amounts written on their options lot (i.e. - /// the OptionLotClaimIndex data structions) weighted by the ratio of exercised to unexercised - /// options on each of those days. - /// @inheritdoc IOptionSettlementEngine + /// the OptionLotClaimIndex data structions) weighted by the ratio of exercised to + /// unexercised options on each of those days. function redeem(uint256 claimId) external { (uint160 optionKey, uint96 claimNum) = decodeTokenId(claimId); diff --git a/src/interfaces/IOptionSettlementEngine.sol b/src/interfaces/IOptionSettlementEngine.sol index 88237be..1746747 100644 --- a/src/interfaces/IOptionSettlementEngine.sol +++ b/src/interfaces/IOptionSettlementEngine.sol @@ -11,7 +11,7 @@ interface IOptionSettlementEngine { // /*////////////////////////////////////////////////////////////// - // Events + // Events //////////////////////////////////////////////////////////////*/ /** @@ -101,7 +101,7 @@ interface IOptionSettlementEngine { event ExerciseAssigned(uint256 indexed claimId, uint256 indexed optionId, uint112 amountAssigned); /*////////////////////////////////////////////////////////////// - // Errors + // Errors //////////////////////////////////////////////////////////////*/ /** @@ -213,7 +213,7 @@ interface IOptionSettlementEngine { error AmountWrittenCannotBeZero(); /*////////////////////////////////////////////////////////////// - // Data structures + // Data structures //////////////////////////////////////////////////////////////*/ /// @dev This enumeration is used to determine the type of an ERC1155 subtoken in the engine. @@ -384,7 +384,7 @@ interface IOptionSettlementEngine { function exercise(uint256 optionId, uint112 amount) external; /*////////////////////////////////////////////////////////////// - // Redeem Option Lot Claims + // Redeem Claims //////////////////////////////////////////////////////////////*/ /** From 1e0a9ecb71d20964388f3672d1efd8e5a21a118b Mon Sep 17 00:00:00 2001 From: neodaoist Date: Fri, 18 Nov 2022 10:58:39 -0500 Subject: [PATCH 12/16] Standardize name --- .gas-snapshot | 2 +- test/{OptionSettlement.t.sol => OptionSettlementEngine.t.sol} | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) rename test/{OptionSettlement.t.sol => OptionSettlementEngine.t.sol} (99%) diff --git a/.gas-snapshot b/.gas-snapshot index 265d705..c760791 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -17,7 +17,7 @@ OptionSettlementTest:testFuzzExercise(uint112,uint112) (runs: 256, μ: 402548, ~ OptionSettlementTest:testFuzzNewOptionType(uint96,uint96,uint40,uint40) (runs: 256, μ: 124682, ~: 124682) OptionSettlementTest:testFuzzRedeem(uint112,uint112) (runs: 256, μ: 393324, ~: 397146) OptionSettlementTest:testFuzzWrite(uint112) (runs: 256, μ: 318433, ~: 318433) -OptionSettlementTest:testFuzzWriteExerciseRedeem(uint32) (runs: 256, μ: 11496773, ~: 11689637) +OptionSettlementTest:testFuzzWriteExerciseRedeem(uint32) (runs: 256, μ: 11511849, ~: 11689637) OptionSettlementTest:testGetClaimForTokenId() (gas: 377614) OptionSettlementTest:testGetOptionForTokenId() (gas: 124586) OptionSettlementTest:testInitial() (gas: 7857) diff --git a/test/OptionSettlement.t.sol b/test/OptionSettlementEngine.t.sol similarity index 99% rename from test/OptionSettlement.t.sol rename to test/OptionSettlementEngine.t.sol index 341caa5..3b4f8ec 100644 --- a/test/OptionSettlement.t.sol +++ b/test/OptionSettlementEngine.t.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.11; import "forge-std/Test.sol"; import {IERC20} from "forge-std/interfaces/IERC20.sol"; + import "../src/OptionSettlementEngine.sol"; /// @notice Receiver hook utility for NFT 'safe' transfers From b38c34219eb1b382bd3e4399cb7d193280a4a7d8 Mon Sep 17 00:00:00 2001 From: neodaoist Date: Fri, 18 Nov 2022 11:31:25 -0500 Subject: [PATCH 13/16] Add OZ credit --- src/interfaces/IERC1155.sol | 125 ++++++++++++++++++++++++++++ src/interfaces/IERC1155Metadata.sol | 114 +++---------------------- src/interfaces/IERC165.sol | 5 +- 3 files changed, 138 insertions(+), 106 deletions(-) create mode 100644 src/interfaces/IERC1155.sol diff --git a/src/interfaces/IERC1155.sol b/src/interfaces/IERC1155.sol new file mode 100644 index 0000000..aac0d46 --- /dev/null +++ b/src/interfaces/IERC1155.sol @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol) + +pragma solidity ^0.8.0; + +import "./IERC165.sol"; + +/** + * @dev Required interface of an ERC1155 compliant contract, as defined in the + * https://eips.ethereum.org/EIPS/eip-1155[EIP]. + * + * _Available since v3.1._ + */ +interface IERC1155 is IERC165 { + /** + * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. + */ + event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); + + /** + * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all + * transfers. + */ + event TransferBatch( + address indexed operator, + address indexed from, + address indexed to, + uint256[] ids, + uint256[] values + ); + + /** + * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to + * `approved`. + */ + event ApprovalForAll(address indexed account, address indexed operator, bool approved); + + /** + * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. + * + * If an {URI} event was emitted for `id`, the standard + * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value + * returned by {IERC1155MetadataURI-uri}. + */ + event URI(string value, uint256 indexed id); + + /** + * @dev Returns the amount of tokens of token type `id` owned by `account`. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function balanceOf(address account, uint256 id) external view returns (uint256); + + /** + * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. + * + * Requirements: + * + * - `accounts` and `ids` must have the same length. + */ + function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) + external + view + returns (uint256[] memory); + + /** + * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, + * + * Emits an {ApprovalForAll} event. + * + * Requirements: + * + * - `operator` cannot be the caller. + */ + function setApprovalForAll(address operator, bool approved) external; + + /** + * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. + * + * See {setApprovalForAll}. + */ + function isApprovedForAll(address account, address operator) external view returns (bool); + + /** + * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. + * + * Emits a {TransferSingle} event. + * + * Requirements: + * + * - `to` cannot be the zero address. + * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. + * - `from` must have a balance of tokens of type `id` of at least `amount`. + * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the + * acceptance magic value. + */ + function safeTransferFrom( + address from, + address to, + uint256 id, + uint256 amount, + bytes calldata data + ) external; + + /** + * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. + * + * Emits a {TransferBatch} event. + * + * Requirements: + * + * - `ids` and `amounts` must have the same length. + * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the + * acceptance magic value. + */ + function safeBatchTransferFrom( + address from, + address to, + uint256[] calldata ids, + uint256[] calldata amounts, + bytes calldata data + ) external; +} \ No newline at end of file diff --git a/src/interfaces/IERC1155Metadata.sol b/src/interfaces/IERC1155Metadata.sol index f88c87b..e7fcc7a 100644 --- a/src/interfaces/IERC1155Metadata.sol +++ b/src/interfaces/IERC1155Metadata.sol @@ -1,116 +1,22 @@ // SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol) -pragma solidity 0.8.11; +pragma solidity ^0.8.0; -import "./IERC165.sol"; +import "./IERC1155.sol"; /** - * @dev Required interface of an ERC1155 compliant contract, as defined in the - * https://eips.ethereum.org/EIPS/eip-1155[EIP]. + * @dev Interface of the optional ERC1155MetadataExtension interface, as defined + * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP]. * * _Available since v3.1._ */ -interface IERC1155Metadata is IERC165 { +interface IERC1155MetadataURI is IERC1155 { /** - * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. - */ - event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); - - /** - * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all - * transfers. - */ - event TransferBatch( - address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values - ); - - /** - * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to - * `approved`. - */ - event ApprovalForAll(address indexed account, address indexed operator, bool approved); - - /** - * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. - * - * If an {URI} event was emitted for `id`, the standard - * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value - * returned by {IERC1155MetadataURI-uri}. - */ - event URI(string value, uint256 indexed id); - - /** - * @dev Returns the amount of tokens of token type `id` owned by `account`. - * - * Requirements: - * - * - `account` cannot be the zero address. - */ - function balanceOf(address account, uint256 id) external view returns (uint256); - - /** - * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. - * - * Requirements: - * - * - `accounts` and `ids` must have the same length. - */ - function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) - external - view - returns (uint256[] memory); - - /** - * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, - * - * Emits an {ApprovalForAll} event. + * @dev Returns the URI for token type `id`. * - * Requirements: - * - * - `operator` cannot be the caller. + * If the `\{id\}` substring is present in the URI, it must be replaced by + * clients with the actual token type ID. */ - function setApprovalForAll(address operator, bool approved) external; - - /** - * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. - * - * See {setApprovalForAll}. - */ - function isApprovedForAll(address account, address operator) external view returns (bool); - - /** - * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. - * - * Emits a {TransferSingle} event. - * - * Requirements: - * - * - `to` cannot be the zero address. - * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}. - * - `from` must have a balance of tokens of type `id` of at least `amount`. - * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the - * acceptance magic value. - */ - function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external; - - /** - * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. - * - * Emits a {TransferBatch} event. - * - * Requirements: - * - * - `ids` and `amounts` must have the same length. - * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the - * acceptance magic value. - */ - function safeBatchTransferFrom( - address from, - address to, - uint256[] calldata ids, - uint256[] calldata amounts, - bytes calldata data - ) external; - function uri(uint256 id) external view returns (string memory); -} +} \ No newline at end of file diff --git a/src/interfaces/IERC165.sol b/src/interfaces/IERC165.sol index dd7d2f9..5fa6551 100644 --- a/src/interfaces/IERC165.sol +++ b/src/interfaces/IERC165.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) -pragma solidity 0.8.11; +pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the @@ -21,4 +22,4 @@ interface IERC165 { * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); -} +} \ No newline at end of file From 74ca1b6d04b5bba8ac65f9e7ca9ca35aa194bdb5 Mon Sep 17 00:00:00 2001 From: neodaoist Date: Fri, 18 Nov 2022 12:00:16 -0500 Subject: [PATCH 14/16] Update natspec --- .gas-snapshot | 2 +- README.md | 2 +- src/OptionSettlementEngine.sol | 37 +++------ src/TokenURIGenerator.sol | 26 +++--- src/interfaces/IOptionSettlementEngine.sol | 93 ++++++++++++++++------ 5 files changed, 96 insertions(+), 64 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index c760791..181a8f0 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -17,7 +17,7 @@ OptionSettlementTest:testFuzzExercise(uint112,uint112) (runs: 256, μ: 402548, ~ OptionSettlementTest:testFuzzNewOptionType(uint96,uint96,uint40,uint40) (runs: 256, μ: 124682, ~: 124682) OptionSettlementTest:testFuzzRedeem(uint112,uint112) (runs: 256, μ: 393324, ~: 397146) OptionSettlementTest:testFuzzWrite(uint112) (runs: 256, μ: 318433, ~: 318433) -OptionSettlementTest:testFuzzWriteExerciseRedeem(uint32) (runs: 256, μ: 11511849, ~: 11689637) +OptionSettlementTest:testFuzzWriteExerciseRedeem(uint32) (runs: 256, μ: 11528117, ~: 11689637) OptionSettlementTest:testGetClaimForTokenId() (gas: 377614) OptionSettlementTest:testGetOptionForTokenId() (gas: 124586) OptionSettlementTest:testInitial() (gas: 7857) diff --git a/README.md b/README.md index 9a1b586..8e7861c 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ The structure of an option is as follows: - **Underlying amount:** the amount of the underlying asset contained within an option of this type. - **Exercise asset:** the ERC-20 address of the asset needed for exercise. - **Exercise amount:** the amount of the exercise asset required to exercise this option. -- **Earliest exercise timestamp:** the timestamp after which this option can be exercised and physically settled. +- **Exercise timestamp:** the timestamp after which this option can be exercised and physically settled. - **Expiry timestamp:** the timestamp before which this option can be exercised. The Core is unopinionated on the type of option (call vs. put), where, when, or for how much an option is bought/sold, and whether or not the option is profitable when exercised. Because all options written with Valorem are fully collateralized, physical settlement at exercise or redeem time is instant and gas-efficient. diff --git a/src/OptionSettlementEngine.sol b/src/OptionSettlementEngine.sol index 7ee7fac..75a14a9 100644 --- a/src/OptionSettlementEngine.sol +++ b/src/OptionSettlementEngine.sol @@ -21,7 +21,7 @@ import "./TokenURIGenerator.sol"; */ /// @title A settlement engine for options -/// @dev This settlement protocol does not support rebase tokens, or fee on transfer tokens +/// @dev This settlement protocol does not support rebasing, fee-on-transfer, or ERC-777 tokens /// @author 0xAlcibiades /// @author Flip-Liquid /// @author neodaoist @@ -178,36 +178,13 @@ contract OptionSettlementEngine is ERC1155, IOptionSettlementEngine { // Token ID Encoding //////////////////////////////////////////////////////////////*/ - /** - * @notice Encode the supplied option id and claim id - * @dev Option and claim token ids are encoded as follows: - * - * MSb - * 0000 0000 0000 0000 0000 0000 0000 0000 ┐ - * 0000 0000 0000 0000 0000 0000 0000 0000 │ - * 0000 0000 0000 0000 0000 0000 0000 0000 │ 160b option key, created from hash of Option struct - * 0000 0000 0000 0000 0000 0000 0000 0000 │ - * 0000 0000 0000 0000 0000 0000 0000 0000 │ - * 0000 0000 0000 0000 0000 0000 0000 0000 ┘ - * 0000 0000 0000 0000 0000 0000 0000 0000 ┐ - * 0000 0000 0000 0000 0000 0000 0000 0000 │ 96b auto-incrementing option lot claim number - * 0000 0000 0000 0000 0000 0000 0000 0000 ┘ - * LSb - * @param optionKey The optionKey to encode - * @param claimNum The claimNum to encode - * @return tokenId The encoded token id - */ + /// @inheritdoc IOptionSettlementEngine function encodeTokenId(uint160 optionKey, uint96 claimNum) public pure returns (uint256 tokenId) { tokenId |= (uint256(optionKey) << 96); tokenId |= uint256(claimNum); } - /** - * @notice Decode the supplied token id - * @dev See encodeTokenId() for encoding scheme - * @param tokenId The token id to decode - * @return optionKey claimNum The decoded components of the id as described above, padded as required - */ + /// @inheritdoc IOptionSettlementEngine function decodeTokenId(uint256 tokenId) public pure returns (uint160 optionKey, uint96 claimNum) { // move key to LSB to fit into uint160 optionKey = uint160(tokenId >> 96); @@ -601,10 +578,12 @@ contract OptionSettlementEngine is ERC1155, IOptionSettlementEngine { uint160(uint256(keccak256(abi.encode(optionRecord.settlementSeed, unexercisedBucketsIndex)))); } + /// @dev Help find a given days bucket by calculating days after epoch function _getDaysBucket() internal view returns (uint16) { return uint16(block.timestamp / 1 days); } + /// @dev Get the amount of exercised and unexercised options for a given claim + day bucket combo function _getAmountExercised(OptionLotClaimIndex storage claimIndex, OptionsDayBucket storage claimBucketInfo) internal view @@ -616,7 +595,7 @@ contract OptionSettlementEngine is ERC1155, IOptionSettlementEngine { claimBucketInfo.amountExercised, claimIndex.amountWritten, claimBucketInfo.amountWritten ); - // The ration of unexercised to written options in the bucket multiplied by the + // The ratio of unexercised to written options in the bucket multiplied by the // number of options actually written in the claim. _unexercised = FixedPointMathLib.mulDivDown( claimBucketInfo.amountWritten - claimBucketInfo.amountExercised, @@ -625,6 +604,7 @@ contract OptionSettlementEngine is ERC1155, IOptionSettlementEngine { ); } + /// @dev Get the exercise and underlying amounts for a claim function _getPositionsForClaim(uint160 optionId, uint256 claimId, Option storage optionRecord) internal view @@ -640,6 +620,7 @@ contract OptionSettlementEngine is ERC1155, IOptionSettlementEngine { } } + /// @dev Help with internal options bucket accounting function _addOrUpdateClaimBucket(uint160 optionId, uint112 amount) internal returns (uint16) { OptionsDayBucket[] storage claimBucketsInfo = _claimBucketByOption[optionId]; uint16[] storage unexercised = _unexercisedBucketsByOption[optionId]; @@ -673,6 +654,7 @@ contract OptionSettlementEngine is ERC1155, IOptionSettlementEngine { return bucketIndex; } + /// @dev Help with internal claim bucket accounting function _updateUnexercisedBucketIndices( uint160 optionId, uint16 bucketIndex, @@ -682,6 +664,7 @@ contract OptionSettlementEngine is ERC1155, IOptionSettlementEngine { _doesBucketIndexHaveUnexercisedOptions[optionId][bucketIndex] = true; } + /// @dev Help with internal claim bucket accounting function _addOrUpdateClaimIndex(uint256 claimId, uint16 bucketIndex, uint112 amount) internal { OptionLotClaimIndex storage lastIndex; OptionLotClaimIndex[] storage claimIndexArray = _claimIdToClaimIndexArray[claimId]; diff --git a/src/TokenURIGenerator.sol b/src/TokenURIGenerator.sol index 7202551..b8a37f1 100644 --- a/src/TokenURIGenerator.sol +++ b/src/TokenURIGenerator.sol @@ -6,28 +6,31 @@ import "solmate/tokens/ERC20.sol"; import "./interfaces/IOptionSettlementEngine.sol"; +/// @title Library to dynamically generate Valorem token URIs library TokenURIGenerator { + /// @notice This struct contains params to generate the token URI struct TokenURIParams { - // The underlying asset to be received + /// @param underlyingAsset The underlying asset to be received address underlyingAsset; - // The symbol of the underlying asset + /// @param underlyingSymbol The symbol of the underlying asset string underlyingSymbol; - // The address of the asset needed for exercise + /// @param exerciseAsset The address of the asset needed for exercise address exerciseAsset; - // The symbol of the underlying asset + /// @param exerciseSymbol The symbol of the underlying asset string exerciseSymbol; - // The timestamp after which this option may be exercised + /// @param exerciseTimestamp The timestamp after which this option may be exercised uint40 exerciseTimestamp; - // The timestamp before which this option must be exercised + /// @param expiryTimestamp The timestamp before which this option must be exercised uint40 expiryTimestamp; - // The amount of the underlying asset contained within an option contract of this type + /// @param underlyingAmount The amount of the underlying asset contained within an option contract of this type uint96 underlyingAmount; - // The amount of the exercise asset required to exercise this option + /// @param exerciseAmount The amount of the exercise asset required to exercise this option uint96 exerciseAmount; - // Option or Claim + /// @param tokenType Option or Claim IOptionSettlementEngine.Type tokenType; } + /// @dev Construct the token URI function constructTokenURI(TokenURIParams memory params) public view returns (string memory) { string memory svg = generateNFT(params); @@ -51,6 +54,7 @@ library TokenURIGenerator { /* solhint-enable quotes */ } + /// @dev Generate the name field function generateName(TokenURIParams memory params) public pure returns (string memory) { (uint256 month, uint256 day, uint256 year) = _getDateUnits(params.expiryTimestamp); @@ -73,6 +77,7 @@ library TokenURIGenerator { ); } + /// @dev Generate the description field function generateDescription(TokenURIParams memory params) public pure returns (string memory) { return string( abi.encodePacked( @@ -89,6 +94,7 @@ library TokenURIGenerator { ); } + /// @dev Generate the image field function generateNFT(TokenURIParams memory params) public view returns (string memory) { uint8 underlyingDecimals = ERC20(params.underlyingAsset).decimals(); uint8 exerciseDecimals = ERC20(params.exerciseAsset).decimals(); @@ -205,7 +211,7 @@ library TokenURIGenerator { ); } - // UTILITIES + /// @notice Utilities struct DecimalStringParams { // significant figures of decimal uint256 sigfigs; diff --git a/src/interfaces/IOptionSettlementEngine.sol b/src/interfaces/IOptionSettlementEngine.sol index 1746747..be6de50 100644 --- a/src/interfaces/IOptionSettlementEngine.sol +++ b/src/interfaces/IOptionSettlementEngine.sol @@ -8,8 +8,6 @@ import "./IERC1155Metadata.sol"; /// @author Flip-Liquid /// @author neodaoist interface IOptionSettlementEngine { - // - /*////////////////////////////////////////////////////////////// // Events //////////////////////////////////////////////////////////////*/ @@ -30,8 +28,8 @@ interface IOptionSettlementEngine { * @param underlyingAsset The contract address of the underlying asset. * @param exerciseAmount The amount of the exercise asset to be exercised. * @param underlyingAmount The amount of the underlying asset in the option. - * @param exerciseTimestamp The timestamp for exercising the option. - * @param expiryTimestamp The expiry timestamp of the option. + * @param exerciseTimestamp The timestamp after which this option can be exercised. + * @param expiryTimestamp The timestamp before which this option can be exercised. * @param nextClaimNum The next claim ID. */ event NewOptionType( @@ -233,9 +231,9 @@ interface IOptionSettlementEngine { address exerciseAsset; /// @param exerciseAmount The amount of the exercise asset required to exercise this option uint96 exerciseAmount; - /// @param exerciseTimestamp The timestamp after which this option may be exercised + /// @param exerciseTimestamp The timestamp after which this option can be exercised uint40 exerciseTimestamp; - /// @param expiryTimestamp The timestamp before which this option must be exercised + /// @param expiryTimestamp The timestamp before which this option can be exercised uint40 expiryTimestamp; /// @param settlementSeed Random seed created at the time of option type creation uint160 settlementSeed; @@ -243,12 +241,14 @@ interface IOptionSettlementEngine { uint96 nextClaimNum; } - /// @dev This struct contains the data about a lot of options written for a particular option type. - /// When writing an amount of options of a particular type, the writer will be issued an ERC 1155 NFT - /// that represents a claim to the underlying and exercise assets of the options lot, to be claimed after - /// expiry of the option. The amount of each (underlying asset and exercise asset) paid to the claimant upon - /// redeeming their claim NFT depends on the option type, the amount of options written in their options lot - /// (represented in this struct) and what portion of their lot was exercised before expiry. + /** + * @dev This struct contains the data about a lot of options written for a particular option type. + * When writing an amount of options of a particular type, the writer will be issued an ERC 1155 NFT + * that represents a claim to the underlying and exercise assets of the options lot, to be claimed after + * expiry of the option. The amount of each (underlying asset and exercise asset) paid to the claimant upon + * redeeming their claim NFT depends on the option type, the amount of options written in their options lot + * (represented in this struct) and what portion of their lot was exercised before expiry. + */ struct OptionLotClaim { /// @param amountWritten The number of options written in this option lot claim uint112 amountWritten; @@ -256,9 +256,11 @@ interface IOptionSettlementEngine { bool claimed; } - /// @dev Options lots are able to have options added to them on after the initial writing. - /// This struct is used to keep track of how many options in a single lot are - /// written on each day, in order to correctly perform fair assignment. + /** + * @dev Options lots are able to have options added to them on after the initial + * writing. This struct is used to keep track of how many options in a single lot + * are written on each day, in order to correctly perform fair assignment. + */ struct OptionLotClaimIndex { /// @param amountWritten The amount of options written on a given day/bucket uint112 amountWritten; @@ -266,9 +268,11 @@ interface IOptionSettlementEngine { uint16 bucketIndex; } - /// @dev Represents the total amount of options written and exercised for a group of - /// claims bucketed by day. Used in fair assignement to calculate the ratio of - /// underlying to exercise assets to be transferred to claimants. + /** + * @dev Represents the total amount of options written and exercised for a group of + * claims bucketed by day. Used in fair assignement to calculate the ratio of + * underlying to exercise assets to be transferred to claimants. + */ struct OptionsDayBucket { /// @param amountWritten The number of options written in this bucket uint112 amountWritten; @@ -278,7 +282,9 @@ interface IOptionSettlementEngine { uint16 daysAfterEpoch; } - /// @dev Struct used in returning data regarding positions underlying a claim or option + /** + * @dev Struct used in returning data regarding positions underlying a claim or option. + */ struct Underlying { /// @param underlyingAsset address of the underlying asset erc20 address underlyingAsset; @@ -333,16 +339,53 @@ interface IOptionSettlementEngine { */ function isOptionInitialized(uint160 optionKey) external view returns (bool); + /*////////////////////////////////////////////////////////////// + // Token ID Encoding + //////////////////////////////////////////////////////////////*/ + + /** + * @notice Encode the supplied option id and claim id + * @dev Option and claim token ids are encoded as follows: + * + * MSb + * 0000 0000 0000 0000 0000 0000 0000 0000 ┐ + * 0000 0000 0000 0000 0000 0000 0000 0000 │ + * 0000 0000 0000 0000 0000 0000 0000 0000 │ 160b option key, created from hash of Option struct + * 0000 0000 0000 0000 0000 0000 0000 0000 │ + * 0000 0000 0000 0000 0000 0000 0000 0000 │ + * 0000 0000 0000 0000 0000 0000 0000 0000 ┘ + * 0000 0000 0000 0000 0000 0000 0000 0000 ┐ + * 0000 0000 0000 0000 0000 0000 0000 0000 │ 96b auto-incrementing option lot claim number + * 0000 0000 0000 0000 0000 0000 0000 0000 ┘ + * LSb + * @param optionKey The optionKey to encode + * @param claimNum The claimNum to encode + * @return tokenId The encoded token id + */ + function encodeTokenId(uint160 optionKey, uint96 claimNum) external pure returns (uint256 tokenId); + + /** + * @notice Decode the supplied token id + * @dev See encodeTokenId() for encoding scheme + * @param tokenId The token id to decode + * @return optionKey claimNum The decoded components of the id as described above, padded as required + */ + function decodeTokenId(uint256 tokenId) external pure returns (uint160 optionKey, uint96 claimNum); + /*////////////////////////////////////////////////////////////// // Write Options //////////////////////////////////////////////////////////////*/ - // /** - // * @notice Create a new options type from optionInfo if it doesn't already exist - // * @dev The supplied creation timestamp and next claim Id fields will be disregarded. - // * @param optionInfo The optionInfo from which a new type will be created - // * @return optionId The optionId for the option. - // */ + /** + * @notice Create a new option type if it doesn't already exist + * @param underlyingAsset The contract address of the underlying asset. + * @param underlyingAmount The amount of the underlying asset in the option. + * @param exerciseAsset The contract address of the exercise asset. + * @param exerciseAmount The amount of the exercise asset to be exercised. + * @param exerciseTimestamp The timestamp after which this option can be exercised. + * @param expiryTimestamp The timestamp before which this option can be exercised. + * @return optionId The optionId for the option. + */ function newOptionType( address underlyingAsset, uint96 underlyingAmount, From b05643e28818326e460a9ed518c74261ffcf339e Mon Sep 17 00:00:00 2001 From: neodaoist Date: Fri, 18 Nov 2022 12:01:58 -0500 Subject: [PATCH 15/16] Lint --- src/interfaces/IERC1155.sol | 16 +++------------- src/interfaces/IERC1155Metadata.sol | 2 +- src/interfaces/IERC165.sol | 2 +- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/src/interfaces/IERC1155.sol b/src/interfaces/IERC1155.sol index aac0d46..5b31989 100644 --- a/src/interfaces/IERC1155.sol +++ b/src/interfaces/IERC1155.sol @@ -22,11 +22,7 @@ interface IERC1155 is IERC165 { * transfers. */ event TransferBatch( - address indexed operator, - address indexed from, - address indexed to, - uint256[] ids, - uint256[] values + address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** @@ -96,13 +92,7 @@ interface IERC1155 is IERC165 { * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ - function safeTransferFrom( - address from, - address to, - uint256 id, - uint256 amount, - bytes calldata data - ) external; + function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. @@ -122,4 +112,4 @@ interface IERC1155 is IERC165 { uint256[] calldata amounts, bytes calldata data ) external; -} \ No newline at end of file +} diff --git a/src/interfaces/IERC1155Metadata.sol b/src/interfaces/IERC1155Metadata.sol index e7fcc7a..c65a3a7 100644 --- a/src/interfaces/IERC1155Metadata.sol +++ b/src/interfaces/IERC1155Metadata.sol @@ -19,4 +19,4 @@ interface IERC1155MetadataURI is IERC1155 { * clients with the actual token type ID. */ function uri(uint256 id) external view returns (string memory); -} \ No newline at end of file +} diff --git a/src/interfaces/IERC165.sol b/src/interfaces/IERC165.sol index 5fa6551..e8cdbdb 100644 --- a/src/interfaces/IERC165.sol +++ b/src/interfaces/IERC165.sol @@ -22,4 +22,4 @@ interface IERC165 { * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); -} \ No newline at end of file +} From 200e748073a208a8700b27ee8cbfb51bd18c8156 Mon Sep 17 00:00:00 2001 From: neodaoist Date: Fri, 18 Nov 2022 12:12:19 -0500 Subject: [PATCH 16/16] Pin pragma for slither --- lib/base64/src/Base64.sol | 2 +- src/interfaces/IERC1155.sol | 2 +- src/interfaces/IERC1155Metadata.sol | 2 +- src/interfaces/IERC165.sol | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/base64/src/Base64.sol b/lib/base64/src/Base64.sol index 578defe..da4a0cf 100644 --- a/lib/base64/src/Base64.sol +++ b/lib/base64/src/Base64.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Base64.sol) -pragma solidity ^0.8.0; +pragma solidity 0.8.11; /** * @dev Provides a set of functions to operate with Base64 strings. diff --git a/src/interfaces/IERC1155.sol b/src/interfaces/IERC1155.sol index 5b31989..a2c3c68 100644 --- a/src/interfaces/IERC1155.sol +++ b/src/interfaces/IERC1155.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol) -pragma solidity ^0.8.0; +pragma solidity 0.8.11; import "./IERC165.sol"; diff --git a/src/interfaces/IERC1155Metadata.sol b/src/interfaces/IERC1155Metadata.sol index c65a3a7..87e9923 100644 --- a/src/interfaces/IERC1155Metadata.sol +++ b/src/interfaces/IERC1155Metadata.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol) -pragma solidity ^0.8.0; +pragma solidity 0.8.11; import "./IERC1155.sol"; diff --git a/src/interfaces/IERC165.sol b/src/interfaces/IERC165.sol index e8cdbdb..9177148 100644 --- a/src/interfaces/IERC165.sol +++ b/src/interfaces/IERC165.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) -pragma solidity ^0.8.0; +pragma solidity 0.8.11; /** * @dev Interface of the ERC165 standard, as defined in the