-
Notifications
You must be signed in to change notification settings - Fork 245
aragonOS 4: Updates to aragonOS and aragon apps
NOTE: A migration guide and updated documentation are available on hack.aragon.org
- Since: 01-04-2018 (
@aragon/[email protected]
) - To: 25-10-2018 (
@aragon/[email protected]
)
Numerous improvements to both the underlying framework, aragonOS
,
as well as the "first-party" applications built on top of it, aragon-apps
,
have been completed over summer 2018.
At a future point in time, the information provided in this document will be available to developers under our documentation website.
Auditing checkpoints:
-
aragonOS: audit-review-freeze tag (
05ee60d2
) -
aragon-apps: audit-review-freeze tag (
cb199980
)
Efforts around aragonOS 4
have focused on new concepts and interfaces
that aim to make it easier for application developers to create and deploy safe
contracts.
These introductions fall under two main categories:
- Contract lifecycle guarantees; and
- Application capabilities
Lifecycle guarantees govern the stages of "life" a deployed contract may fall under, as well as their expected functionality at any given stage. Primarily, these guarantees should help avoid confusion over whether a certain contract can be used directly, or only as a base logic contract behind another proxy contract.
Application capabilities are feature extensions available through AragonApp
that may extend functionality in a given way. These include:
- ETH and token recoverability (new; enabled by default)
- Natively depositable proxies for ETH (new; disabled by default)
- EVMScript (included by default)
- Forwarding interface (not included by default)
Lifecycle guarantees were partly available in aragonOS 3
through the
Initializable
contract, which was included with AragonApp
.
aragonOS 4
introduces Petrifiable
, as well as AutoPetrified
, (see
changeset) to ensure that
deployed base contracts are never utilizable. Petrifiable
is built as an
extension to Initializable
, with the behaviour that contracts who are
"petrified" can be assumed to be never initialized. AutoPetrified
petrifies a
contract on deployment, through the constructor.
The main use case for Petrifiable
is to mark base contracts as unusable, to
allow developers to control whether they want their application contracts to be
usable directly through the deployed contract or only via a proxy contract.
By default, AragonApp
now inherits from AutoPetrified
, so all application
contracts building from AragonApp
will be petrified by default. It is
important to note that making sure this is the case is still the responsibility
of the application developer, as he has to protect any publicly-accessible
functionality from being accessible in a petrified state himself.
Some additional hasInitialized()
checks are included in AragonApp
and
Kernel
to make this responsibility less bothersome (e.g. including it in the
auth
modifier and canPerform()
).
The contract lifecycle of an AragonApp
now looks like this:
Not deployed ---> Base deployed (immediately petrified and assumed unusable)
|
|---> Proxy deployed ---> Proxy initialized (now usable)
With Petrifiable
, applications now must be initialized before they can be
used, even if they had no use for initialization before.
Any attempt at initializing or using AragonApp
base contracts should fail if the
application developer has successfully secured their contract. By making base contracts
unusable we can provide additional assurance that they will always be available and they
cannot be self-destructed.
Additionally, aragonOS
provides a "backdoor" to AragonApp
through
UnsafeAragonApp
, which disables this default protection to allow application
developers to create contracts which can be directly used without a proxy.
In the case of UnsafeAragonApp
, the lifecycle looks like:
Not deployed ---> Base deployed --> Base initialized (now usable)
|
|---> Proxy deployed ---> Proxy initialized (now usable)
Only the depositable proxies and escape hatch recoverability are new since 01-04-2018.
@aragon/[email protected]
introduced the concept of depositable proxies (see original
changeset and additional
changeset to disable it by default).
Depositable proxies were designed to enhance application proxies to allow them
to receive ETH on native, gas-limited, .send()
s and .transfer()
s due to the
gas calculations of DelegateProxy
s. This functionality relied on the gas
limit for a call.
Afterwards, in @aragon/[email protected]
, we added the ability to enable and
disable ETH depositability inside apps, and disable it by default so that most
application contracts would not behave differently based on the amount of gas
sent to a call.
Right now, both AragonApp
s and Kernel
s should not able to receive ETH
whether in their base contracts, or in a proxy. Most tokens, of course, we
can't control.
@aragon/[email protected]
also introduced the concept of ETH and token recoverability
(see changeset).
The transferToVault()
escape hatch included in AragonApp
s and Kernel
s is
intended for users to be able to recover any mistakenly sent ETH or tokens to a
defined "default" vault for the organization. Note that, again, AragonApp
s
and Kernel
s (and their proxies) are not able to receive ETH by default.
An allowRecoverability()
hook is included for application contracts to define
their own behaviour regarding recoverability.
This capability can be nuanced for application contracts that are meant to hold
or receive ETH or tokens. For example, the Token Manager
is meant to hold and
control minted organization tokens, and so should prevent recoverability for
those tokens. Another example is the Vault
, which should prevent
recoverability altogether when initialized. A further point of complexity is
changing an app's default recoverability capabilities based on its
lifecycle–Finance
is recoverable only when not initialized, to avoid ETH or
tokens being locked in an ususable contract.
Apps must be connected to a Kernel
instance for them to be usable, if they use the authorization checks properly (part of changeset for Petrifiable
).
Apps instantiated through Kernel.newAppInstance()
or
Kernel.newPinnedAppInstance()
can now be directly initialized by providing the calldata for
the initialization call, which is executed right after the proxy is created
(changeset).
The Kernel
now uses an explicit two-level mapping for app namespacing rather
than using a hash of concatenated bytes (changeset).
All contracts have been upgraded to [email protected]
(changeset).
Proxies are now implemented via unstructured storage (changeset).
This additional abstraction allows application contracts inheriting from
AragonApp
to start at slot 0, simplifying their storage model, as well as
making it easier to upgrade in the future.
DelegateScript
and DeployDelegateScript
were removed, as they weren't being
used and we could not find a satisfiable method of making them safe
(changeset).
Important changes are highlighted in bold. Breaking changes from aragonOS 3
are noted with [Breaking]
.
Lists raw contract changes.
-
cdaed71
(25-10-2018): Document and fix potentially uninitialized bytes array when force castingbytes
to and fromuint256[]
-
e3fb067
(23-10-2018):[Breaking]
Publicly exposeEVMScriptRunner.getEVMScriptRegistry()
-
9406059
(23-10-2018):[Breaking]
Prune unnecessary public constants to optimize gas during deployment -
c469d8f
(22-10-2018): Add clarification comments about howIsContract
is meant to be used a684791
(16-10-2018): Add revert reasons-
683d4f8
(08-10-2018): Remove redundantkernel
check inAragonApp.getRecoveryVault()
-
7d70ffe
(08-10-2018):[Breaking]
ChangeEVMScriptRegistry
's executor storage to a mapping instead of an array -
f67fa5d
(08-10-2018): Use non-strict pragma forKernelConstants
as it's inherited byAragonApp
-
7a5078a
(28-09-2018): Add the ability to "burn" permission managers, so as to throw away or freeze a permission permanently -
8d2f97d
(28-09-2018):[Breaking]
ChangeRepo
's storage of versions to a mapping instead of an array -
c7f001b
(18-09-2018): Fix visibility order for constants -
88619af
(05-09-2018): Optimize multiplication inSafeMath64
andSafeMath8
-
7fca564
(04-09-2018): UseTimeHelpers
inACL
a56234e
(04-09-2018):[Breaking]
Allow depositable functionality to be enabled or disabled, and default to disablede07c379
(04-09-2018):[Breaking]
Allow apps to be initialized when being instantiated from aKernel
5b880fc
(03-09-2018):[Breaking]
Use explicit mappings inKernel
for different namespaces rather than using a hash of concatenated bytes-
94f70e5
(30-08-2018): Useauth
modifier inACL
-
d268367
(27-08-2018):[Breaking]
Remove unused token contracts from libraries -
f94d43d
(27-08-2018): Add functionality to allow re-enabling executors inEVMScriptRegistry
bfed147
(26-08-2018):[Breaking]
Upgrade to[email protected]
-
5bec9d0
(23-08-2018):[Breaking]
Always check that base contracts are a contract 1e4ce6c
(22-08-2018):[Breaking]
AddPetrifiable
-
3e5c75d
(22-08-2018):[Breaking]
Use explicit nonces to calculate hashes in theACL
-
db0ecb6
(22-08-2018):[Breaking]
Remove sender param fromACL
1ee632b
(22-08-2018):[Breaking]
Move to unstructured storage-
ae97af2
(22-08-2018): Add type getter to EVMScript executors -
5064958
(22-08-2018): Emit events when enabling or disabling executors inEVMScriptRegistry
-
4b873bb
(15-08-2018): UpdateSafeMath
libraries to current gas-optimized versions -
796ebfd
(15-08-2018): Log when permissions are set with parameters -
898310f
(10-08-2018): AddTimeHelpers
andUintHelpers
to use the same interface for obtaininguint64
time values -
1c2ba2c
(01-08-2018): Add another helper toACLSyntaxSugar
-
2392a50
(27-07-2018): Use static types more, rather than rawaddresses
-
6466d21
(26-07-2018): Add log for EVM script result after execution -
540c4ae
(26-07-2018): Make fallbacks external -
623c498
(25-07-2018): Remove obsoletekernelIntegrity
modifier -
9e673e7
(13-07-2018): AddSafeMath8
for math operations onuint8
s -
f3ba361
(13-07-2018): Explicitly define state visibility be4522b
(06-06-2018): [Breaking
] RemoveDelegateScript
andDeployDelegateScript
executors-
b127811
(24-04-2018): Use hardcoded constants instead ofkeccak
ing strings to save gas -
2e77439
(15-05-2018):[Breaking]
Fix incorrect role hashes in APM apps -
b8691e9
(14-04-2018):[Breaking]
Emit app IDs in new app proxy event 5f24c49
(14-05-2018): Depositable proxies and escape hatches for recoverability-
9b1bdd2
(15-04-2018): Remove unnecessary reimplementation of fallback inAppProxyPinned
-
19e386e
(15-04-2018): Minor gas improvements -
29d7d11
(04-04-2018):[Breaking]
Fix app ID hashes
The majority of the work in aragon-apps
has been to upgrading to aragonOS 4
(changeset), including
a simplification to the Vault
that adds native ETH support (which also had
rippling effects for Finance
).
A small migration guide for the apps is provided in #422:
- Upgrade to
pragma solidity 0.4.24
- Upgrade to
[email protected]
and[email protected]
; doing so requires that any test contracts be placed incontracts/
- All apps are required to be initialized before they can be used
- Unnecessary to use
isInitialized
modifier if theauth
orauthP
modifier is used - Changed import locations of
@aragon/os/contracts/lib/zeppelin/{token,math}
to be@aragon/os/contracts/lib/{token,math}
- Removed token implementations (
StandardToken
andMinimeToken
) from aragonOS - Apps inheriting from
AragonApp
are automatically petrified upon deployment, so any tests directly using the base contract will fail and need updating (e.g.Finance
andSurvey
)
50a841a
(23-10-2018): Large gas optimizations by only storing moststring
data in events-
66ccde1
(23-10-2018): Update radspec -
c12c59f
(17-10-2018): Further state optimizations by packing moreuint256
s intouint64
s cdaee27
(16-10-2018): Add revert reasons0caee4a
(18-09-2018): Move all protection modifiers in all (e.g. initialization) to be in externally accessible interfaces, to simplify mental model of when protection checks are needed89d80c4
(18-09-2018): Use mappings instead of arrays for storage, to aid struct upgradeability-
6193cc0
(18-09-2018): Cosmetic improvements for comments, code style -
dbc0990
(17-09-2018): Upgrade toaragonOS 4
(also upgrading topragma solidity 0.4.24
)- Also includes changes for the simplified
Vault
- Also includes changes for the simplified
- Initialization checks:
a69551b
,5c44f9b
, and finally superseded by the upgrade toaragonOS 4
-
5cdff73
(24-07-2018): Explicitly define state visibility -
40d87c8
(03-04-2018): UseSafeMath
more in all apps
Capability matrix:
Lifecycle | Recoverability | Depositability |
---|---|---|
Petrified (with Kernel) | State impossible | State impossible |
Petrified (without Kernel) | False | False |
Uninitialized | True | False |
Initialized | False | False |
Base contract will be petrified on deployment.
Depositing to the Finance's proxy is disabled, but assets can be deposited to the finance.vault()
.
Finance provides its own custom deposit functionality that creates a record and sends funds to the vault.
Changes:
- Depositing
- Fix budgeting
-
4cce038
(01-08-2018): AddhasBudget
toauth
modifiers forCHANGE_BUDGETS_ROLE
-
2f4813d
(24-07-2018): Don't usetransitionsPeriod
ongetBudget()
as getters should be constant -
6eefcc6
(24-07-2018): Set the budget to 0 when removing a budget -
f10105f
(25-04-2018): ExposegetRemainingBudget()
and only return budget settings fromgetBudget()
-
- Improve period transitions
f17bf63
(26-07-2018): Remove limit on number of period transitions per transaction-
29b1662
(24-07-2018): AddtransitionsPeriod
to fallback -
ccf9883
(26-04-2018): Set minimum period duration to 1 day -
8a2f035
(25-04-2018): Avoid reverting on overflow when transitioning periods c36b8e9
(25-04-2018): RefactortryTransitionAccountingPeriod()
into a loop instead of recursion
- Misc
-
7e3303a
(25-10-2018): Add comments explaining whysetPaymentStatus()
doesn't transition periods -
3e97d90
(25-10-2018): Radspec adjustments -
ebc5b04
(16-10-2018): RenamesetPaymentDisabled()
tosetPaymentStatus()
, and rename role toMANAGE_PAYMENTS_ROLE
to better reflect capability -
9b29427
(19-09-2018): Optimize storage variables by consistently usinguint64
-
39c12b3
(18-09-2018): Make uint constants internal -
c10c08d
(18-09-2018): Reorder state variables -
9b75bc8
(24-07-2018): Make fallback external -
61335b8
(25-04-2018): Pass amount toauth
check when executing recurring payment -
a52f369
(25-04-2018): Include amount in recorded transaction event -
7b30e2c
(25-04-2018): Include payment repeat number in recorded transactions -
f424938
(25-04-2018): Only allow a recurring payment to be created if it can be executed at least once
-
Capability matrix:
Lifecycle | Recoverability | Depositability |
---|---|---|
Petrified (with Kernel) | State impossible | State impossible |
Petrified (without Kernel) | False | False |
Uninitialized | False | False |
Initialized | True (only for non-managed token) | False |
Base contract will be petrified on deployment.
Changes:
3b2ec3c
(18-09-2018): Math optimizations to remove unnecessary usages of SafeMath-
7ea3c53
(18-09-2018): Cosmetic function reordering 7c0ef11
(18-09-2018): Remove logging of token holders-
671b400
(18-09-2018): Remove unnecessary function for getting vesting length 389fcdb
(17-09-2018 as part of upgrade toaragonOS 4
): Disable recoverability for managed token-
4f2d9a7
(25-04-2018): Add more information to vesting events 95635e3
(25-04-2018): Offload all responsibility for handling untrasferable tokens to the Minime token
The Vault
has been completely redone and simplified. The current vault is
intended to only hold ETH and ERC20 tokens, with simple access controls for
transferring held funds.
Capability matrix:
Lifecycle | Recoverability | Depositability |
---|---|---|
Petrified (with Kernel) | State impossible | State impossible |
Petrified (without Kernel) | False | False |
Uninitialized | False | False |
Initialized | False | True |
Base contract will be petrified on deployment.
Changes:
23057c4
(16-10-2018): Only transfer ETH with.transfer()
rather than an arbitrary.call()
with data-
d8d70e3
(16-10-2018): Remove unnecessary_from
parameter as it's alwaysmsg.sender
- Original changeset, which has been superseded by the upgrade to
aragonOS 4
Capability matrix:
Lifecycle | Recoverability | Depositability |
---|---|---|
Petrified (with Kernel) | State impossible | State impossible |
Petrified (without Kernel) | False | False |
Uninitialized | True | False |
Initialized | True | False |
Base contract will be petrified on deployment.
Changes:
-
6addb83
(23-10-2018): RenametotalVoters
tovotingPower
for clarity and consistency -
5621d4f
(16-10-2018): Only allow votes to be created if the token snapshot is positive -
0e8f3a5
(08-10-2018): Tweak radspec a1050d9
(19-09-2018): Change voting thresholds to use strict inequality checks (rather than "or equal to" checks) to better mimic real world use cases-
738387c
(18-09-2018): Allow the required support threshold to be changed, needed for Multisigs, when adding more addresses d946356
(17-09-2018): Add parameter when creating a new vote whether it should automatically execute when possible-
79e9aec
(17-09-2018): Cosmetic reordering of quorum sanity checks a149c05
(16-05-2018): Fixes for calculating if a vote passed its thresholds-
db615e7
(23-04-2018): Allow a vote to be created but not voted on immediately by the creator
We now document our deployments in aragon/deployments
.
Contracts inheriting from AragonApp
are meant to be deployed by third-party
developers, to be installable by organizations to extend their functionality.
Our official apps, aragon-apps
, include the Finance
, TokenManager
,
Vault
, and Voting
contracts that will be petrified on deployment and only
usable behind a proxy (either AppUpgradeableProxy
or AppPinnedProxy
) by
users who create an organization.
aragonOS
includes two other applications inheriting from AragonApp
–the
ACL
and EVMScriptRegistry
–that will be petrified on deployment and only
usable behind a proxy by users. By default, the EVMScriptRegistry
will
include a reference to a deployed CallsScript
executor, that includes the
logic for sending calls scripts (essentially batched function calls).
The Kernel
contract in aragonOS
will be the backbone for each organization,
and its base contract will also be petrified on deployment so as to force users
to only use it behind a proxy (KernelProxy
).
Finally, aragonOS
also includes a number of factory contracts (DAOFactory
,
EVMScriptFactory
) that will be deployed and used directly by other factories
(e.g. those in DAO-kits
) to create
organizations for users. See aragonOS/scripts/deploy-daofactory.js
for how
these factories will be deployed.
For the most part, we foresee most users interacting with only the deployed factories to create organizations through a web frontend. These factories will atomically and deterministically create, initialize, and set up permissions on the organization and its installed applications in one transaction, to avoid any potentially dangerous states (e.g. a contract not being initialized or set up properly). Users should not be deploying their own base contracts, unless they specifically desire to do so, and it will be their responsibility to ensure those contract are correctly used.
After using a factory, users will interact with the application proxies
installed on their organizations for functionality like depositing ETH or
tokens, voting, etc. Users may also install new applications, although at this
point only technical users will access this functionality as it requires either
sending raw transactions or using
aragon-cli
.
The Aragon Package Manager ("APM") is meant to be a generic on-chain repository of contracts and associated code. For more information, see Deploying and Distributing Aragon Core.
Right now, all the code for APM lives in aragonOS
.
The AragonApp
s comprising the Aragon Package Manager, APMRegistry
and
Repo
, will be deployed and used behind proxies by a "Aragon Package Manager"
DAO.
aragonOS
includes the ENSFactory
and APMRegistryFactory
contracts to
create new instances of APM. See aragonOS/scripts/deploy-beta-ens.js
and
aragonOS/scripts/deploy-beta-apm.js
for how these factories will be deployed.