Contract Overview 
Files 
- EIP-2535 Diamond Proxy related: - Diamond.sol: proxy contract itself
- facets/: each Diamond Facet contract in the system. These contain every- externalfunction, or every user facing function in the system
- libraries/DataTypes.sol: all structs used
- libraries/AppStorage.sol: single struct that contains all data in the diamond
- libraries/LibXXX.sol: shared internal library functions that may be used across any of the facets. These are inlined into each facet when deployed.
 
- contracts/interfaces/: separate interfaces not auto-generated in- interfaces/
- bridges/: standalone contracts to bridge between between ETH and staked ETH.- BridgeReth.sol: bridge to deposit rETH into dETH
- BridgeSteth.sol: bridge to deposit stETH into dETH
 
- governance/: governance contracts for DAO
- libraries/: bulk of shared logic contained in library files that are inserted into Facets
- mocks/: mock files for Chainlink, Lido, Rocket Pool
- tokens/- /Asset.sol: base ERC-20 used in the system.- dETH.sol(via- Asset.sol): stablecoin for ETH backed by liquid staking derivative (no yield)
- dUSD.sol(via- Asset.sol): stablecoin for USD, backed by dETH
 
- Ditto.sol(via- tokens/Asset.sol): DAO token
 
- deploy/: deploy scripts
- interfaces/: auto generated folder by running a script that reads all Facets and produces interfaces from- .solfiles. It's useful to check- IDiamond.solwhich includes all facets.
Modifiers 
- onlyDAO: Verifies the caller is the owner of the diamond contract. Owner is currently the DittoTimelockController, which is governed by the DittoDAO. 
- onlyAdminOrDAO: Verifies the caller is the admin or the DittoDAO, which allows for quicker responses to time sensitive actions. 
- nonReentrantView: Reentrancy guard for view functions. Only applicable for protocols integrating with DittoETH. 
- onlyDiamond: Checks that the caller is the diamond contract. This is to give privileged access to certain external functions. - onlyDAO - onlyAdminOrDAO - nonReentrantView - onlyDiamond - withdrawTapp - shutdownMarket - getDethTotal - deposit (bridge) - transferOwnership - cancelOrderFarFromOracle - getCollateralRatio - depositEth (bridge) - setVault - transferAdminship - getCollateralRatioSpotPrice - withdraw (bridge) - createBridge - setTithe - getAssetCollateralRatio - createForcedBid - deleteBridge - setDittoMatchedRate - getBids - createMarket - setDittoShorterRate - getAsks - diamondCut¹ - setInitialCR - getShorts - setLiquidationCR - getShortIdAtOracle - setMinAskEth - getShortRecord - setForcedBidPriceBuffer - getShortRecords - setPenaltyCR - getShortRecordCount - setWithdrawalFee - getDethBalance - setMinShortErc - getAssetBalance - setMinBidEth - getUndistributedYield - setTappFeePct - getYield - setCallerFeePct - getDittoMatchedReward - setRecoveryCR - getDittoReward - getAssetUserStruct - getAssetStruct - getVaultUserStruct - getVaultStruct - getBridgeStruct - ¹ onlyDAO is enforced via - enforceIsContractOwner()in- LibDiamond.sol
- nonReentrant: Prevents calling another nonReentrant function within the diamond proxy. 
- isNotFrozen: Checks that the asset is not frozen. 
- onlyValidAsset: Checks if the address passed as the asset belongs to the system. 
- isFrozen: Checks that the asset being called is frozen. 
- onlyValidShortRecord: Checks that a short record is valid for a given asset, user, and id. 
- isPermanentlyFrozen: Checks that an asset is not permanently frozen. - nonReentrant - isNotFrozen - isPermanentlyFrozen - onlyValidAsset - onlyValidShortRecord - cancelAsk() - ✅ - ✅ - cancelBid() - ✅ - ✅ - cancelOrderFarFromOracle() - ✅ - ✅ - cancelShort() - ✅ - ✅ - claimDittoMatchedReward() - ✅ - claimRedemption() - ✅ - ✅ - claimRemainingCollateral() - ✅ - ✅ - combineShorts() - ✅ - ✅ - ✅ - createAsk() - ✅ - ✅ - ✅ - createBid() - ✅ - ✅ - ✅ - createLimitShort() - ✅ - ✅ - ✅ - decreaseCollateral() - ✅ - ✅ - ✅ - deposit() - ✅ - depositAsset() - ✅ - ✅ - ✅ - depositEth() - ✅ - disputeRedemption() - ✅ - ✅ - distributeYield() - ✅ - ✅ ¹ - exitShort() - ✅ - ✅ - ✅ - exitShortErcEscrowed() - ✅ - ✅ - ✅ - exitShortWallet() - ✅ - ✅ - ✅ - increaseCollateral() - ✅ - ✅ - ✅ - liquidate() - ✅ - ✅ - ✅ - liquidateSecondary() - ✅ - ✅ - ✅ - proposeRedemption() - ✅ - ✅ - redeemErc() - ✅ - ✅ - shutdownMarket() - ✅ - ✅ - ✅ - updateYield() - ✅ - withdraw() - ✅ - withdrawAsset() - ✅ - ✅ - withdrawDittoReward() - ✅ - ¹ Modifier is on internal function call - _distributeYield, which is inside a loop in the top level- distributeYieldcall.
Testing 
Chainlink, Lido, Rocket Pool mocked in the tests
- scripts/: misc scripts for during dev
- test/: unit tests- test/utils/OBFixture.sol: setup to create all contracts, helper functions used in tests, init code
 
Gas Testing 
FOUNDRY_PROFILE=gasto deploy with the optimizer. Specific tests for gas to try to isolate the estimated gas per function by trying to take into account the cost of warm/cold storage slots.
- test-gas/: specific tests for average gas usage. Set profile to be compiled using optimizer.- test-gas/GasHelper.sol: same for the gas tests. Adds the- startMeasuringGas/- stopMeasuringGashelpers.
 
- .gas.json: Gas is written to separate temp files, and- npm run gasupdates them to JSON.
Optimizations 
DittoETH utilizes several gas saving optimizations to bring down the gas cost of using the system. As a general rule, optimizations were focused on the 80% use case.
- Diamond Proxy: Requires two external calls, but gives internal access to storage and library calls.
- Struct packing: See the STypeslibrary inDataTypes.solto see how storage slots are allocated for struct variables. Struct variables that are commonly accessed and wrote to are put into the same slot if possible.
- Hint system: Users or frontends must pass a hint to accurately find the accurate place in bidOrders,askOrders,shortOrderslinked lists. This reduces the need for iterating over a large number of Orders.
- Reuse IDs: Ids are recycled after use for the following storage variables: bidOrders,askOrders,shortOrders, andshortRecords. This is applicable for theSTypes.OrdersandSTypes.ShortRecordsstructs. The cost to set storage after initial use goes down from 20k to 5k gas because the slots are not cleared after use.
- Utilize unused storage: Constants.HEADof thebidOrdersmapping represents the HEAD of the linked list and is never used as an order. This allowsercAmountandcreationTimeto be repurposed fororaclePriceandoracleTime. This is abstracted in the codebase as thesetPriceAndTimefunction.- Another instance is using the Diamond proxyaddress, which isaddress(this)as theTAPPaddress in some of the mappings.
 
- Another instance is using the 
- Keep Storage Non-Zero: In YieldFacet,dittoMatchedSharesanddittoRewardare left at 1wei, which effectively serves as zero and avoids the evm penalty of setting storage of a zeroed slot in subsequent calls.
- Virtual Accounting: dETH and stable assetsare tracked virtually, which are only burned and minted when entering and exiting the system. This reduces the need for an external call to the ERC-20 fortransfer,mint,burn, ect.
- Store Oracle Data: External (live) oracle data is only queried when certain conditions have been met. Otherwise, the system uses an internally stored price and time.
