Skip to content

Commit

Permalink
Finalize AccountRecoveryManager and UpgradeBeaconControllerManager
Browse files Browse the repository at this point in the history
  • Loading branch information
0age committed Oct 29, 2019
1 parent c85344c commit 548be8f
Show file tree
Hide file tree
Showing 12 changed files with 545 additions and 166 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ These contracts have been audited by Trail of Bits - <a href="https://github.com
## Contract Deployment Addresses & Verified Source Code
| Core Contracts | Implementations | Factories |
|-------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------|
| <a href="https://etherscan.io/address/0x00000000005330029d3de861454979d0dd8c89dc#code" target="_blank">DharmaUpgradeBeaconControllerManager</a> | Dharma Smart Wallet | Dharma Smart Wallet |
| <a href="https://etherscan.io/address/0x000000000000d64cc9d4c7d2a573d7205926677a#code" target="_blank">DharmaUpgradeBeaconControllerManager</a> | Dharma Smart Wallet | Dharma Smart Wallet |
| <a href="https://etherscan.io/address/0x00000000002226c940b74d674b85e4be05539663#code" target="_blank">DharmaUpgradeBeaconController</a> | <a href="https://etherscan.io/address/0x0000000053d300f11703dcdd1e90921db83f0048#code" target="_blank">AdharmaSmartWalletImplementation</a> | <a href="https://etherscan.io/address/0xfc00c80b0000007f73004edb00094cad80626d8d#code" target="_blank">DharmaSmartWalletFactoryV1</a> |
| <a href="https://etherscan.io/address/0x000000000026750c571ce882b17016557279adaa#code" target="_blank">DharmaUpgradeBeacon</a> | <a href="https://etherscan.io/address/0x0000000010a653849f221a573e00f3a37c8c4082#code" target="_blank">DharmaSmartWalletImplementationV1</a> | DharmaSmartWalletFactoryV2 |
| <a href="https://etherscan.io/address/0x00000000011df015e8ad00d7b2486a88c2eb8210#code" target="_blank">DharmaKeyRingUpgradeBeaconController</a> | <a href="https://etherscan.io/address/0x000000000088387c42fe85a60df4dce8e34eea4e#code" target="_blank">DharmaSmartWalletImplementationV2</a> | |
| <a href="https://etherscan.io/address/0x0000000000bda2152794ac8c76b2dc86cba57cad#code" target="_blank">DharmaKeyRingUpgradeBeacon</a> | DharmaSmartWalletImplementationV3 | Dharma Key Ring |
| <a href="https://etherscan.io/address/0x000000000067503c398f4c9652530dbc4ea95c02#code" target="_blank">DharmaUpgradeBeaconEnvoy</a> | | <a href="https://etherscan.io/address/0x00dd005247b300f700cfdff89c00e2acc94c7b00#code" target="_blank">DharmaKeyRingFactoryV1</a> |
| <a href="https://etherscan.io/address/0x000000005d7065eb9716a410070ee62d51092c98#code" target="_blank">DharmaKeyRegistryV1</a> | Dharma Key Ring | <a href="https://etherscan.io/address/0x2484000059004afb720000dc738434fa6200f49d#code" target="_blank">DharmaKeyRingFactoryV2</a> |
| <a href="https://etherscan.io/address/0x00000000ea4044b4b60091836a6d47554f43a100#code" target="_blank">DharmaKeyRegistryV2</a> | <a href="https://etherscan.io/address/0x00000000480003d5ee4f51134ce73cc9ac00f693#code" target="_blank">AdharmaKeyRingImplementation</a> | DharmaKeyRingFactoryV3 |
| <a href="https://etherscan.io/address/0x00000000003709edea9182789f1153e59cfe849e#code" target="_blank">DharmaAccountRecoveryManager</a> | <a href="https://etherscan.io/address/0x00000000ea0007cdab60e07437e59e9cc41c2e49#code" target="_blank">DharmaKeyRingImplementationV1</a> | |
| <a href="https://etherscan.io/address/0x00000000004cda75701eea02d1f2f9bdce54c10d#code" target="_blank">DharmaAccountRecoveryManager</a> | <a href="https://etherscan.io/address/0x00000000ea0007cdab60e07437e59e9cc41c2e49#code" target="_blank">DharmaKeyRingImplementationV1</a> | |

## Overview
The Dharma Smart Wallet and Dharma Key Ring are designed with the following assumptions in mind:
Expand Down Expand Up @@ -79,12 +79,12 @@ Both the Dharma Smart Wallet and the Dharma Key Ring are upgradeable:
- Like most upgradeable contracts, they utilize a proxy mechanism, where each instance performs a `DELEGATECALL` to an updateable "implementation" contract when called. However, in contrast to most upgradeable proxy contracts, which store an implementation address and an admin address that can change that implementation, smart wallet and key ring instances have no proxy-specific state, and instead retrieve their current implementation from a dedicated [Upgrade Beacon](https://github.com/dharma-eng/dharma-smart-wallet/blob/master/contracts/upgradeability/smart-wallet/DharmaUpgradeBeacon.sol) contract.
- Each upgrade beacon is a minimally-simple contract that has a hard-coded controller and a single storage slot that represents the current implementation. Only the controller may update this storage slot, and the upgrade beacon will return the address contained at that storage slot for any other caller.
- Each [Upgrade Beacon Controller](https://github.com/dharma-eng/dharma-smart-wallet/blob/master/contracts/upgradeability/DharmaUpgradeBeaconController.sol) is an ownable contract that emits events related to each upgrade, enforces some conditions as to what upgrades are allowable, and enables the current owner of the controller to transfer ownership to a new owner.
- The [Dharma Upgrade Beacon Controller Manager](https://github.com/dharma-eng/dharma-smart-wallet/blob/master/contracts/upgradeability/DharmaUpgradeBeaconControllerManager.sol) will own each Upgrade Beacon Controller, and can also support other, future upgrade beacon controllers. It enforces configurable time-locks for each protected function - these include functions for making upgrades, for transferring ownership of controllers, and for modifying the default timelock intervals and other parameters. _(Note: the Upgrade Beacon Controller Manager currently has a known bug that still needs to be fixed, and more tests that need to be written, before it goes into production.)_
- The [Dharma Upgrade Beacon Controller Manager](https://github.com/dharma-eng/dharma-smart-wallet/blob/master/contracts/upgradeability/DharmaUpgradeBeaconControllerManager.sol) will own each Upgrade Beacon Controller, and can also support other, future upgrade beacon controllers. It enforces configurable time-locks for each protected function - these include functions for making upgrades, for transferring ownership of controllers, and for modifying the default timelock intervals and other parameters.
- While all new upgrades have a seven-day timelock, there are two notable exceptions:
- If a bug is introduced in a new upgrade, the Dharma Upgrade Beacon Controller Manager can immediately "downgrade" and roll back to the last implementation.
- If a critical vulnerability is discovered, or if 90 days go by without a "heartbeat" being triggered on the Dharma Upgrade Beacon Controller Manager, an "[Adharma Contingency](https://github.com/dharma-eng/dharma-smart-wallet/blob/master/contracts/implementations/smart-wallet/AdharmaSmartWalletImplementation.sol)" upgrade can be executed on the smart wallet or the key ring. These implementations strip out all but the most basic functionality and give the user direct, singular control over their smart wallet and key ring contracts - basically, it ensures that users can recover their funds, no matter what. A new upgrade can be performed by the Dharma Upgrade Beacon Controller Manager after 48 hours in the contingency state.
- Prior to each upgrade, a prospective implementation needs to first be deployed and registered as a potential upgrade candidate. This gives the community a chance to review the implementation, and to raise any potential concerns or opt-out of the upgrade by withdrawing their funds.
- Once the top-level upgradeability management contract suite is stable and thoroughly tested, ownership of each controller will be transferred to the Dharma Upgrade Beacon Controller Manager - **note that upgradeability is currently managed directly via a secure private key, but that a switch to a multisig-owned Upgrade Beacon Controller Manager is planned in the coming weeks.**
- Once the top-level upgradeability management contract suite has been more thoroughly tested, ownership of each controller will be transferred to the Dharma Upgrade Beacon Controller Manager - **note that upgradeability is currently managed directly via a secure private key, but that a switch to a multisig-owned Upgrade Beacon Controller Manager is planned in the coming weeks.**

## Install
To install locally, you'll need Node.js 10+ and Yarn *(or npm)*. To get everything set up:
Expand Down
54 changes: 26 additions & 28 deletions contracts/account-recovery/DharmaAccountRecoveryManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import "@openzeppelin/contracts/math/SafeMath.sol";
import "../helpers/Timelocker.sol";
import "../helpers/TwoStepOwnable.sol";
import "../../interfaces/DharmaAccountRecoveryManagerInterface.sol";
import "../../interfaces/TimelockerModifiersInterface.sol";

interface DharmaSmartWalletRecovery {
function recover(address newUserSigningKey) external;
Expand Down Expand Up @@ -38,6 +39,7 @@ interface DharmaSmartWalletRecovery {
*/
contract DharmaAccountRecoveryManager is
DharmaAccountRecoveryManagerInterface,
TimelockerModifiersInterface,
TwoStepOwnable,
Timelocker {
using SafeMath for uint256;
Expand Down Expand Up @@ -89,27 +91,6 @@ contract DharmaAccountRecoveryManager is
);
}

/**
* @notice Initiates a timelocked account recovery disablement process for a
* smart wallet. Only the owner may call this function. Once the timelock
* period is complete (and before it has expired) the owner may call
* `disableAccountRecovery` to complete the process and opt a smart wallet out
* of account recovery. Once account recovery has been disabled, it cannot be
* reenabled - the process is irreversible.
* @param smartWallet the smart wallet address.
* @param extraTime Additional time in seconds to add to the timelock.
*/
function initiateAccountRecoveryDisablement(
address smartWallet, uint256 extraTime
) external onlyOwner {
require(smartWallet != address(0), "No smart wallet address provided.");

// Set the timelock and emit a `TimelockInitiated` event.
_setTimelock(
this.disableAccountRecovery.selector, abi.encode(smartWallet), extraTime
);
}

/**
* @notice Timelocked function to set a new user signing key on a smart
* wallet. Only the owner may call this function.
Expand All @@ -132,9 +113,7 @@ contract DharmaAccountRecoveryManager is
);

// Ensure that the timelock has been set and is completed.
_enforceTimelock(
this.recover.selector, abi.encode(smartWallet, newUserSigningKey)
);
_enforceTimelock(abi.encode(smartWallet, newUserSigningKey));

// Declare the proper interface for the smart wallet in question.
DharmaSmartWalletRecovery walletToRecover = DharmaSmartWalletRecovery(
Expand All @@ -157,6 +136,27 @@ contract DharmaAccountRecoveryManager is
emit Recovery(smartWallet, oldUserSigningKey, newUserSigningKey);
}

/**
* @notice Initiates a timelocked account recovery disablement process for a
* smart wallet. Only the owner may call this function. Once the timelock
* period is complete (and before it has expired) the owner may call
* `disableAccountRecovery` to complete the process and opt a smart wallet out
* of account recovery. Once account recovery has been disabled, it cannot be
* reenabled - the process is irreversible.
* @param smartWallet the smart wallet address.
* @param extraTime Additional time in seconds to add to the timelock.
*/
function initiateAccountRecoveryDisablement(
address smartWallet, uint256 extraTime
) external onlyOwner {
require(smartWallet != address(0), "No smart wallet address provided.");

// Set the timelock and emit a `TimelockInitiated` event.
_setTimelock(
this.disableAccountRecovery.selector, abi.encode(smartWallet), extraTime
);
}

/**
* @notice Timelocked function to opt a given wallet out of account recovery.
* This action cannot be undone - any future account recovery would require an
Expand All @@ -169,9 +169,7 @@ contract DharmaAccountRecoveryManager is
require(smartWallet != address(0), "No smart wallet address provided.");

// Ensure that the timelock has been set and is completed.
_enforceTimelock(
this.disableAccountRecovery.selector, abi.encode(smartWallet)
);
_enforceTimelock(abi.encode(smartWallet));

// Register the specified wallet as having opted out of account recovery.
_accountRecoveryDisabled[smartWallet] = true;
Expand Down Expand Up @@ -260,7 +258,7 @@ contract DharmaAccountRecoveryManager is
* given function selector.
* @param extraTime Additional time in seconds to add to the timelock.
*/
function initiateTimelockExpiration(
function initiateModifyTimelockExpiration(
bytes4 functionSelector, uint256 newTimelockExpiration, uint256 extraTime
) external onlyOwner {
// Ensure that a function selector is specified (no 0x00000000 selector).
Expand Down
Loading

0 comments on commit 548be8f

Please sign in to comment.