Closed Oighty closed 8 months ago
Per discussion today, it may be better to use a shorter Keycode, allow versioning, and allow upgrades in the sunset sense with particular IDs referring to specific Modules + versions.
Regarding module upgrades:
Version compatibility:
Modules allow extending the core auction system with additional logic. Inspired by Default Framework, we will use a Keycode system to label and store references to external contracts which implement one of a variety of module interfaces. Standardized functions, as specified in
design/ARCHITECTURE.md
and thesrc/modules/Modules.sol
file, allow for installation, retrieval, and validation of modules.Module Types
Auction
Modules that implement logic for specific types of auctions that sellers can create. They store data about an auction. The AuctionHouse interacts with Auction modules via the standard interface defined in
design/ARCHITECTURE.md
. Auctions do not receive or custody funds, but determine the amount of tokens to sell based on the auction parameters and buyer input.Derivative
Modules that create derivative tokens from an underlying base token. Derivative modules allow auction sellers (or just general users) to offer a derivative of a token for sale instead of just the base token. These modules custody collateral for the particular derivative type that they implement. All Derivative modules are ERC6909 contracts and store data for the tokens they issue locally. They can also optionally wrap the multitoken standard into ERC20 clones for particular token IDs if users need them to be composable with other applications.
Condensor
Auctions have the ability to output additional data about a buyer payout other than the quantity, including parameters to input into the specified Derivative module for the auction. Due to the general way Auctions and Derivatives are defined, they expect inputs in a certain way and output standard data. It is not possible to solve for every possible case on just the Derivative interfaces, so we need a way to combine seller input with auction output data into a format expected by a Derivative module. Condensor modules perform this function by implementing a single
condense
function as specified indesign/ARCHITECTURE.md
. They can be thought of as a link between a specific Auction that outputs extra data and a specific Derivative module.Transformer
An interesting feature of the singleton AuctionHouse design is that the core contract has control over all Derivative types that exist in the system. This allows for certain functionality that wouldn't be available if they were locked down as standalone implementations. Specifically, it allows the AuctionHouse to "break" the derivative rules and unbundle the underlying collateral in cases where it deems it allowable to do so. Allowing this functionality adds some risk, but, if used correctly, can allow for tranforming one derivative into another if the new derivative upholds certain criteria of the existing derivative. They can be thought of as a mapping between a Derivative and another Derivative. A few examples could be:
Module Management
Installation and Replacement of Modules
We've thought extensively about the characteristics of this specific module system in the context of the singleton AuctionHouse design. The
designs/ARCHITECTURE.md
andsrc/modules/Modules
file provide a specification and initial implementation of these concepts. The purpose of these design decisions is discussed here.The Keycode-based identifiers allow for "labeling" specific modules with a name and version instead of needing to know/remember the contract address of the deployed module. The Keycode must be unique. In addition, we can store the address once and then store references to it using the smaller keycode to save storage space. Default framework uses a 5 byte Keycode for Modules and a 20 byte SubKeycode (which includes the parent Keycode in the first 5 bytes) for Submodules. The 5 byte version allows for short, memorable names, but doesn't allow for versioning within the Keycode. This is by design since Modules in the Default Framework are upgradeable, but we want to avoid that in this case, as explained below. The 20 byte SubKeycodes do not save any storage space and are probably a bit overkill for our purposes here. We believe a 10 byte keycode provides adequate room for differentiating or versioning modules within a single variable.
As mentioned above, Modules in this system will not be upgradable. Auctions store information about ongoing auction sales. Derivatives store token data AND custody collateral for the derivative. "Upgrading" them in the Default sense would be expensive (if copying storage and/or transferring assets). On the other hand, we could make the Modules all be Upgradable Proxies, but that opens the door for exploits in the future, especially when the system is decentralized. The safest way to protect ongoing auctions and derivatives is to not allow their code to be updated at all. However, it is possible that there will be bugs in Modules over time and the community may wish to replace a specific version with a new one in this cases. Therefore, we allow Modules to be "sunset" which prohibits new usage of the module, but allows existing auctions to complete and derivative tokens to be redeemed on them. As a replacement, a new Module can be installed with a slightly different Keycode to represent the new version, which clients can update to reference.
Permissioned Functionality on Modules
Modules are able to restrict access to functionality on their contracts to only the AuctionHouse by using the
onlyParent
modifier. We denote which standard functions on the above Module types should be restricted by default in thedesign/ARCHITECTURE.md
specification. In order to make governance streamlined in the future, this should be the only access control used on any Module. While this makes sense for the functionality that was designed to be restricted to the AuctionHouse in the first place, this may sound strange for more administrative cases, such as updating default values in an Auction. As such, we need a way to have "pass-through" administration of a Module via the AuctionHouse. This is accomplished with a genericexecOnSubmodule
function which the owner of the AuctionHouse can use to call any permissioned function on a Module. It may make sense to block certain function signatures that are not administrative (e.g.purchase
on Auction modules ormint
on Derivative modules) from this as a protection against malicious governance in the future.