Skip to content

Commit

Permalink
Removed code from upgrade_mechanism.md
Browse files Browse the repository at this point in the history
  • Loading branch information
Ihor Barenblat committed Apr 28, 2020
1 parent a042906 commit 7aec77f
Showing 1 changed file with 12 additions and 114 deletions.
126 changes: 12 additions & 114 deletions docs/upgrade_mechanism.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,72 +18,17 @@ Use it for a better understanding.

`Upgradeable` is an interface of contract, which knows its **target** (address of implementation). The target can be changed by calling `upgradeTarget` method.

```sol
/// @title Interface of the upgradeable contract
interface Upgradeable {
/// @notice Upgrades target of upgradeable contract
/// @param newTarget New target
/// @param newTargetInitializationParameters New target initialization parameters
function upgradeTarget(address newTarget, bytes calldata newTargetInitializationParameters) external;
}
```

### Proxy

`Proxy` is an interim contract between the caller and the real implementation of the contract.

```sol
/// @title Proxy Contract
contract Proxy is Upgradeable, UpgradeableMaster, Ownable
```
`contract Proxy is Upgradeable, UpgradeableMaster, Ownable`.

**Note: storage of this contract will be a context in which all processes of the target will work.** Proxy will store address of its **target** at the storage slot with index `keccak256("target")`.

As Proxy implements Upgradeable, it can change its target, but only `master` can do it.

Proxy have a fallback function:

```sol
/// @notice Performs a delegatecall to the contract implementation
/// @dev Fallback function allowing to perform a delegatecall to the given implementation
/// This function will return whatever the implementation call returns
function() external payable {
require(msg.data.length > 0, "pfb11"); // pfb11 - calldata must not be empty
address _target = getTarget();
assembly {
// The pointer to the free memory slot
let ptr := mload(0x40)
// Copy function signature and arguments from calldata at zero position into memory at pointer position
calldatacopy(ptr, 0x0, calldatasize)
// Delegatecall method of the implementation contract, returns 0 on error
let result := delegatecall(
gas,
_target,
ptr,
calldatasize,
0x0,
0
)
// Get the size of the last return data
let size := returndatasize
// Copy the size length of bytes from return data at zero position to pointer position
returndatacopy(ptr, 0x0, size)
// Depending on result value
switch result
case 0 {
// End execution and revert state changes
revert(ptr, size)
}
default {
// Return data with length of size at pointers position
return(ptr, size)
}
}
}
```
Proxy have a fallback function that performs a delegatecall to the contract implementation and return whatever the implementation call returns

There is some type of calls that Proxy must intercept without uncheck submitting to processing to a fallback function: calling the `initialize` function (in the right way this function will be called from proxy contract directly) and functions of `UpgradeableMaster` interface (that is a reason why Proxy implements it).

Expand All @@ -101,79 +46,32 @@ When all needed Proxy contracts are deployed, one of them (which must implements

The last part of deploying --- is to transfer mastership of all proxy contracts to the gatekeeper and add them to the gatekeeper's list of managing contracts.

The last will be done by calling several times the next function:

```sol
/// @notice Adds a new upgradeable contract to the list of contracts managed by the gatekeeper
/// @param addr Address of upgradeable contract to add
function addUpgradeable(address addr) external
```
The last should be done by calling several times `addUpgradeable` function.

### Upgrade process

There is three **phases of upgrade** which described in UpgradeGatekeeper:

```sol
/// @notice Upgrade mode statuses
enum UpgradeStatus {
Idle,
NoticePeriod,
Preparation
}
```

* **Idle**
This is a phase when there are no upgrades to process.

* **NoticePeriod**
This phase starts when master of gatekeeper calls next function:
```sol
// @notice Starts upgrade (activates notice period)
/// @param newTargets New managed contracts targets (if element of this array is equal to zero address it means that appropriate upgradeable contract wouldn't be upgraded this time)
function startUpgrade(address[] calldata newTargets) external
```
Sense of this phase - give all users of the rollup contract an opportunity to withdraw funds to the ethereum network before updating the target. The transition to the next phase can be done after at least upgradeNoticePeriod seconds from the start of this phase. upgradeNoticePeriod is a value which defines from some "`mainContract`":
```sol
/// @notice Contract which defines notice period duration and allows finish upgrade during preparation of it
UpgradeableMaster public mainContract;
```
This phase starts when master of gatekeeper calls `startUpgrade` function.
Sense of this phase --- give all users of the rollup contract an opportunity to withdraw funds to the ethereum network before updating the target. The transition to the next phase can be done after at least upgradeNoticePeriod seconds from the start of this phase. `upgradeNoticePeriod` is a value which defines by the "`mainContract`".

* **Preparation**
This is a finish phase. During this phase master can call finishUpgrade function.
```sol
/// @notice Finishes upgrade
/// @param targetsInitializationParameters New targets initialization parameters per each upgradeable contract
function finishUpgrade(bytes[] calldata targetsInitializationParameters) external {
```

One of the most important checks inside this function:
```sol
require(mainContract.readyForUpgrade(), "fpu13"); // fpu13 - main contract is not ready for upgrade
```
This is a finish phase. During this phase master can call `finishUpgrade` function.
One of the most important checks inside this function is enforcing that the mainContract is ready for the upgrade.

## Current Franklin contract upgrade specification or "How notice period works"

`UPGRADE_NOTICE_PERIOD` defined in Config.sol:

```sol
/// @notice Notice period before activation preparation status of upgrade mode (in seconds)
uint constant UPGRADE_NOTICE_PERIOD = 2 weeks;
```
`UPGRADE_NOTICE_PERIOD` defined in Config.sol as 2 weeks.

`Franklin`'s decision about preparing for finishing the upgrade:
```sol
// @notice Checks that contract is ready for upgrade
/// @return bool flag indicating that contract is ready for upgrade
function readyForUpgrade() external returns (bool) {
return !exodusMode && totalOpenPriorityRequests == 0;
}
```
`Franklin` makes a decision that upgrade can be finished when both of these conditions is true:
1. exodus mode is not activated
2. count of open priority requests equals to zero.

To prevent rollup from spamming of priority requests, during `preparation lock period` contract will not add new priority requests.
This period starts from the notification from the gatekeeper about the start of preparation status of upgrade and ends when the upgrade finishes, or after `UPGRADE_PREPARATION_LOCK_PERIOD` seconds from its start.

The last is defined in Config.sol:
```sol
/// @notice Period after the start of preparation upgrade when contract wouldn't register new priority operations (in seconds)
uint constant UPGRADE_PREPARATION_LOCK_PERIOD = 1 days;
```
`UPGRADE_PREPARATION_LOCK_PERIOD` is defined in Config.sol as 1 day.

0 comments on commit 7aec77f

Please sign in to comment.