-
Notifications
You must be signed in to change notification settings - Fork 2
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
document dynamic primitive (erc-721) #41
Changes from 1 commit
636a3f9
8d5cc1c
27798b2
1130d2e
c65ec55
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,7 +1,13 @@ | ||||||||||||
# Dynamic ERC721 | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It may be better to just call this a "dynamic primitive" in general and just list which standards we support inside the page somewhere (currently only ERC721). Otherwise, we're going to have to copy the entire page content for every primitive we add dynamic support for (and if we support the partial fields in the config, it might end up being all of them) |
||||||||||||
|
||||||||||||
This primitive allows registering new erc721 extensions in runtime, triggered by | ||||||||||||
a generic smart contract event. | ||||||||||||
This primitive allows registering new [ERC721](ERC721) extensions in runtime, | ||||||||||||
triggered by a generic smart contract event. This works by having a smart | ||||||||||||
contract that has an event that acts as a *trigger* to the engine, and the | ||||||||||||
engine in response adds a new extension, without needing to change the | ||||||||||||
configuration file. An use-case for this would be a factory contract, which | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||
takes care of deploying new instances of the contract tracked by the newly | ||||||||||||
generated primitive, and then emits and event to signal the engine to start | ||||||||||||
tracking this through an event. | ||||||||||||
|
||||||||||||
## Configuration | ||||||||||||
|
||||||||||||
|
@@ -12,35 +18,74 @@ extensions: | |||||||||||
type: "dynamic-primitive" | ||||||||||||
startBlockHeight: 100 | ||||||||||||
contractAddress: "0x5FbDB2315678afecb367f032d93F642f64180aa3" | ||||||||||||
scheduledPrefix: "derc721" | ||||||||||||
burnScheduledPrefix: "bderc721" | ||||||||||||
eventSignature: "CustomEvent(address)" | ||||||||||||
abiPath: "./CustomEventEmitter.json" | ||||||||||||
targetType: "erc721" | ||||||||||||
fields: | ||||||||||||
contractAddress: address | ||||||||||||
targetConfig: | ||||||||||||
type: "erc721" | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We didn't add the ability for some fields to be optionally present, did we?
|
||||||||||||
scheduledPrefix: "nft" | ||||||||||||
burnScheduledPrefix: "nftburn" | ||||||||||||
dynamicFields: | ||||||||||||
contractAddress: nftAddress | ||||||||||||
``` | ||||||||||||
|
||||||||||||
### Meaning | ||||||||||||
|
||||||||||||
There are two type of fields in this configuration. The top level fields are | ||||||||||||
used for the extension that have the role of monitoring the network for the | ||||||||||||
trigger event. These are the following: | ||||||||||||
|
||||||||||||
- `contractAdress` is the address of the smart contract that will emit the event that will trigger the erc721 primitive creation. | ||||||||||||
- `scheduledPrefix` and `burnScheduledPrefix` are the prefixes used for the | ||||||||||||
resulting erc721 events. This primitive won't emit events by itself. See [the | ||||||||||||
erc721 section for details](ERC721#meaning). | ||||||||||||
- `abiPath`, specifying a path to a .json file describing the compiled contract | ||||||||||||
– the only field required in this file is the `abi` field in the top-level | ||||||||||||
object; | ||||||||||||
- `eventSignature`, specifying the signature of the event consisting only of the event name followed by parameter types (without names) in order, enclosed in parentheses and separated by commas. | ||||||||||||
- `fields.contractAddress` should have the name of the field in the emitted event. | ||||||||||||
|
||||||||||||
The nested fields instead are used to construct the configurations for the | ||||||||||||
dynamically generated extensions. It's divided into a static part, which is in | ||||||||||||
`targetConfig`. And a dynamic part which is in `dynamicFields`. Dynamic in this | ||||||||||||
context means that it depends on the data included on the emitted event. | ||||||||||||
|
||||||||||||
#### Static configuration | ||||||||||||
|
||||||||||||
- `scheduledPrefix` and `burnScheduledPrefix` are the prefixes used for the | ||||||||||||
resulting ERC721 events. This primitive won't emit events by itself. See [the | ||||||||||||
ERC721 section for details](ERC721#meaning). | ||||||||||||
|
||||||||||||
#### Dynamic configuration | ||||||||||||
|
||||||||||||
- `contractAddress` has the name of the field in the emitted event that contains | ||||||||||||
the address of the ERC721. | ||||||||||||
|
||||||||||||
The example configuration assumes that the event has the following signature: | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should also make it very clear whether or not the event emission can contain more parameters than needed, and if the position of the argument matters |
||||||||||||
|
||||||||||||
```solidity | ||||||||||||
event CustomEvent(address indexed address); | ||||||||||||
event CustomEvent(address indexed nftAddress); | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we want a full example of a Solidity contract for this, we can use // SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract CustomERC721 is ERC721 {
constructor(string memory name, string memory symbol) ERC721(name, symbol) {}
}
contract FactoryERC721 {
event ERC721Created(address indexed nftAddress); // emitted when ERC721 token is deployed
/// @dev deploys an ERC721 token with given parameters
/// @return address deployed
function deployERC721(string memory _name, string memory symbol) public returns (address) {
CustomERC721 t = new CustomERC721(_name, symbol);
emit ERC721Created(address(t));
return address(t);
}
} |
||||||||||||
``` | ||||||||||||
|
||||||||||||
The `contractAddress` fields needs to be changed to the name of the field in the | ||||||||||||
event otherwise. | ||||||||||||
## Utility functions | ||||||||||||
|
||||||||||||
Generated extensions have a _name_, that is derived from the name of the trigger | ||||||||||||
extension, and the order of the dynamic primitive. The following function can be | ||||||||||||
used to generate this name. | ||||||||||||
|
||||||||||||
```ts | ||||||||||||
export function generateDynamicPrimitiveName(parentName: string, id: number): string; | ||||||||||||
``` | ||||||||||||
|
||||||||||||
For example, the first dynamic primitive that gets created will have a name of | ||||||||||||
`generateDynamicPrimitiveName(parentCdeName, 0)`, and so on. This name can be | ||||||||||||
ecioppettini marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||
then used as an argument to the other utility functions. | ||||||||||||
|
||||||||||||
There is also a public utility function to get the list of all of the | ||||||||||||
dynamically generated extensions. In this case the `config` field is formatted | ||||||||||||
as json. It can be used to extract, the contract address, for example. | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably this should contain a link to I'm assuming you're talking about the extensions config? I'm just guessing this is what you were referring to. |
||||||||||||
|
||||||||||||
```ts | ||||||||||||
export async function getDynamicExtensions( | ||||||||||||
readonlyDBConn: Pool, | ||||||||||||
parent: string | ||||||||||||
): Promise<{ name: string; config: string }[]>; | ||||||||||||
``` | ||||||||||||
|
||||||||||||
## Performance implications | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably a block of text is not the most readable way to convey this. I would suggest either a a picture or a list of steps. Something like:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
why rollup? what are we using that term for? I'm not sure I get it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Your game is a rollup that monitors multiple primitives |
||||||||||||
|
||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel this is a conceptually complex feature with multiple subtle things to take into account and I feel the docs are too short to properly be addressing all of these. Additionally, it's not clear from the docs how you would write a smart contract in a way to trigger dynamic primitive so we should probably provide a concrete example of this and discuss best practices like factory contracts