owned this note
owned this note
Published
Linked with GitHub
# RFC: EVMScripter API Specification
## Types
### Action
Object of type `{ to: Address, data: String, value?: BigNumber }`.
### AppIdentifier
String with format `<AppName>[:<Label>]`. Regular expression for parser: `^(?!-)[A-Za-z0-9-]{1,63}(?<!-)(:(?!-)[A-Za-z0-9-]{1,63}(?<!-))?$`.
* AppName: Name of the app as it appears in the APM. String of type `^(?!-)[A-Za-z0-9-]{1,63}(?<!-)$`.
* Label: Used when more than one app of the same type is installed. It usually is numeric, starting from 0, The user can also define non-numeric labels to identify new installed apps.
### LabeledAppIdentifier
Extends `AppIdentifier` but requires the label not to be numeric. It is used for distinguishing already installed apps grabbed from Aragon Connect, and counterfactual apps that will be installed by the EVMScript.
### Entity: AppIdentifier | Address
It can be an app or any other address.
### Permission: [Entity, Entity, String]
List of three elements: Grantee, App, and Role.
### CompletePermission: [Entity, Entity, String, Entity]
List of four elements: Grantee, App, Role, and Permission Manager.
### ForwardOptions
Object of type `{ path: Entity[], context: string}`
### App
Object of type `ConnectApp & { abiInterface: Interface }`
It extends the `App` type defined by Aragon Connect adding the cached abi ethers interface.
## Operations
### addPermission(permission: Permission, defaultPermissionManager: Entity): Action
It creates or grants a permission: if the permission already exists, it grants it to the new entity. If it doesn't, the script creates it using `defaultPermissionManager` as the permission manager.
### addPermissions(permissions: Permission[], defaultPermissionManager: Entity): Action[]
Creates or grants permissions based in the current permissions table.
**Example**
```js
evm.addPermissions([
['disputable-voting', 'commons-market-maker', 'OPEN_TRADING_ROLE'],
[evm.ANY_ENTITY, 'commons-market-maker', 'MAKE_BUY_ORDER_ROLE'],
[evm.ANY_ENTITY, 'commons-market-maker', 'MAKE_SELL_ORDER_ROLE'],
['disputable-voting', 'commons-market-maker', 'ADD_COLLATERAL_TOKEN_ROLE'],
['commons-market-maker', 'wrappable-hooked-token-manager', 'MINT_ROLE'],
['commons-market-maker', 'wrappable-hooked-token-manager', 'BURN_ROLE'],
['commons-market-maker', 'agent:2', 'TRANSFER_ROLE'],
[hatchMigrationTools, 'migration-tools-beta', 'PREPARE_CLAIMS_ROLE']
['migration-tools-beta', 'wrappable-hooked-token-manager', 'ISSUE_ROLE'],
['migration-tools-beta', 'wrappable-hooked-token-manager', 'ASSIGN_ROLE'],
], 'disputable-voting')
```
### app(app: AppIdentifier): Address
Return the address of an existing or projected app.
### call(app: AppIdentifier): Proxy
It returns a JavaScript [`Proxy`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) class which handles calls to a target object. When a function of the proxy is called, it returns the encoded call to the function contract.
**Example:**
```js
evms.call('token-manager').mint(address, ethers.utils.parseUnits(amount))
```
### connect(dao: ENS | Address): Promise<void>
Uses Aragon Connect to grab information about installed apps, permissions, and ABIs. It stores all the information the library needs, so we won't need any other async operation.
It is necessary before any other action.
### decode(script: String): Action[]
Decodes a script into a list of actions.
### encode(actions: Action[], options: ForwardOptions): Promise<Action>
It encodes all actions in one and call them using the path, using the variable `context` in forwards with context (AragonOS v5).
### forward(actions: Action[], { context: String, path: Entity[] }): TransactionReceipt
Encodes all the actions in a forward call and sends it as a transaction.
### installApp(app: LabeledAppIdentifier, initParams: Any[] = []): Promise<Action>
Returns the action of installing a new app. It must provide a labeled app identifier that will update EVMScripter internal dictionary with the projected address of the app.
**Example:**
```js
evms.installApp('vault:reserve')
evms.installApp('vault:common-pool')
evms.installApp('migration-tools:new', [
evms.app('token-manager'),
evms.app('vault:reserve'),
evms.app('vault:common-pool')
])
```
### permissions(actions: Actions[] = []): CompletePermission[]
If you dont pass actions then it'll return the current dao permissions
If you add actions that change permissions
Returns an array with the resulting permissions after applying the list of `actions`.
It'll throw an error if one of the actions is not the result of adding or revoking permissions.
### radspec(actions: Action[]): String[]
Returns the radspec description of a list of actions.
### revokePermission(permission: Permission, removeManager = true): Action[]
Remove the permission and sets the permission manager to not assigned if `removeManager` is true.
### revokePermissions(permissions: Permission[], removeManager = true): Action[]
**Example**
Removes the permissions and sets the permission manager to not assigned if `removeManager` is true.
```js
evm.revokePermissions([
['dynamic-issuance', 'wrappable-hooked-token-manager', 'MINT_ROLE'],
['dynamic-issuance', 'wrappable-hooked-token-manager', 'BURN_ROLE'],
['disputable-voting', 'dynamic-issuance', 'UPDATE_SETTINGS_ROLE']
])
```
## Future features
### grantPermissionP(...)
Add a granular permissions
### revokePermissionP(...)
Revoke a granular permission
## Commons Upgrade example
```
evm.forward([
evm.installApp('agent'),
evm.installApp('commons-market-maker.open', [
evm.app('wrappable-hooked-token-manager'),
evm.app('agent:1'),
evm.app('agent:2'),
formulaAddress,
parseInt(entryTribute * PPM),
parseInt(exitTribute * PPM)
]),
evm.installApp('migration-tools-beta.open', [
evm.app('wrappable-hooked-token-manager'),
evm.app('agent:1'),
evm.app('agent:2')
]),
evm.addPermissions([
['disputable-voting', 'commons-market-maker', 'OPEN_TRADING_ROLE'],
[evm.ANY_ENTITY, 'commons-market-maker', 'MAKE_BUY_ORDER_ROLE'],
[evm.ANY_ENTITY, 'commons-market-maker', 'MAKE_SELL_ORDER_ROLE'],
['disputable-voting', 'commons-market-maker', 'ADD_COLLATERAL_TOKEN_ROLE'],
['commons-market-maker', 'wrappable-hooked-token-manager', 'MINT_ROLE'],
['commons-market-maker', 'wrappable-hooked-token-manager', 'BURN_ROLE'],
['commons-market-maker', 'agent:2', 'TRANSFER_ROLE'],
[hatchMigrationTools, 'migration-tools-beta', 'PREPARE_CLAIMS_ROLE']
['migration-tools-beta', 'wrappable-hooked-token-manager', 'ISSUE_ROLE'],
['migration-tools-beta', 'wrappable-hooked-token-manager', 'ASSIGN_ROLE'],
], 'disputable-voting')
evm.revokePermissions([
['dynamic-issuance', 'wrappable-hooked-token-manager', 'MINT_ROLE'],
['dynamic-issuance', 'wrappable-hooked-token-manager', 'BURN_ROLE'],
['disputable-voting', 'dynamic-issuance', 'UPDATE_SETTINGS_ROLE']
]),
evm.call['commons-market-maker'].addCollateralToken(collateral, 1, 0, parseInt(reserveRatio * PPM))
], { context, path })
```
----
>
# Notes
token-manager.open != token-manager != token-manager.1hive
const newApps = {}
evm.installer(newApps)('migration-tools-beta', [
evm.app('wrappable-hooked-token-manager'),
evm.app('agent:1'),
evm.app('agent:2')
]),
function installer(obj) {
return function(appName, registry, params) {
//busca abi...
return encodeFunctionData('initialize', params)
}
}
forward([....]) {
const newApps = {'vault-0': '0x0asdasd'}
const installApp = installer(newApps)
for() {
}
}
function context() {
const newApp = {}
operation()
}
const installApp = installer(newApps)
const installCalladata = installApp(appName, registry, params)
const installCalladata = installApp(appName, registry, params)
const installCalladata = installApp(appName, registry, params)
class EVMScripter {
#labels: Map<String, Address>
setLabel(key, value) {
this.#labels.set(key, value)
}
function installApp(appName, registry, params, label: string) {
// ...
const proxyAddress = ....
this.#labels.set(`${appName}:${}`, proxyAddress)
}
}
evmScripter.installApp('vault', 'default', [])