Skip to content
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

design: Fee bridge on old deployment #8756

Closed
Tracked by #7935
LHerskind opened this issue Sep 24, 2024 · 1 comment
Closed
Tracked by #7935

design: Fee bridge on old deployment #8756

LHerskind opened this issue Sep 24, 2024 · 1 comment
Assignees

Comments

@LHerskind
Copy link
Contributor

LHerskind commented Sep 24, 2024

The collateral that is deposited into the fee bridge needs to decide which instance it honours in case of an upgrade.

For example, it is following along, an upgrade would mean that there is no collateral to transfer funds to the sequencer to cover the fees paid in the blocks. If this causes a failure to execute that is essentially bricking the old instance, so it should be possible to address separately.

For example, one might be able to check a value in the original bridge, if it is no longer the rollup itself, it might need to alter the fee bridge.

A separate thing to consider, if this is using multiple different bridges, it will be different types or messages that is received on the L2 side of things. Meaning that the L2 contract might not allow inserting directly unless we can let it learn that things have changed, so we might need to look into either having a contract where assets might be deposited into multiple different rollups, or passing along with the constants the address of the "current" fee bridge.

When design is made, consider #7938 for implementation.

@github-project-automation github-project-automation bot moved this to Todo in A3 Sep 24, 2024
@LHerskind LHerskind added this to the Sequencer & Prover Testnet milestone Sep 24, 2024
LHerskind added a commit that referenced this issue Sep 27, 2024
Slight extension on #8818 to separate gov and instance more clearly. 

Gov does not have dependencies on core, but core can depend on the gov. 

Removes the registry value from the `Rollup` does not address that an
upgrade would make the fee contract unbacked, that is to be handled
separately in #8756.

Updates testing for the `Registry` contract to use the [Branching Tree
Technique](https://www.youtube.com/watch?v=0-EmbNVgFA4) from Paul. Found
it quite neat. If using `bulloak` as well quite convenient to build the
setups.

The TL;DR is, build a `.tree` file outlining the test for a function,
and then use `bulloak scaffold` to prepare a testing file and then fill
in the logic. Makes it quite nice to follow the logic.

# Example time

```.tree
UpgradeTest
├── when caller is not owner
│   └── it should revert
└── when caller is owner
    ├── when rollup already in set
    │   └── it should revert
    └── when rollup not already in set
        ├── it should add the rollup to state
        └── it should emit a {InstanceAdded} event
```

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.27;

import {Test} from "forge-std/Test.sol";

import {Registry} from "@aztec/governance/Registry.sol";

contract RegistryBase is Test {
  Registry internal registry;

  function setUp() public {
    registry = new Registry(address(this));
  }
}
```

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.27;

import {RegistryBase} from "./Base.t.sol";

import {Ownable} from "@oz/access/Ownable.sol";

import {IRegistry} from "@aztec/governance/interfaces/IRegistry.sol";
import {Errors} from "@aztec/governance/libraries/Errors.sol";
import {DataStructures} from "@aztec/governance/libraries/DataStructures.sol";

contract UpgradeTest is RegistryBase {
  function test_RevertWhen_CallerIsNotOwner(address _caller) external {
    // it should revert
    vm.assume(_caller != address(this));
    vm.prank(_caller);
    vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, _caller));
    registry.upgrade(address(uint160(uint256(bytes32("new instance")))));
  }

  modifier whenCallerIsOwner() {
    _;
  }

  function test_RevertWhen_RollupAlreadyInSet() external whenCallerIsOwner {
    // it should revert
    address rollup = registry.getRollup();

    vm.expectRevert(
      abi.encodeWithSelector(Errors.Registry__RollupAlreadyRegistered.selector, rollup)
    );
    registry.upgrade(rollup);
  }

  function test_WhenRollupNotAlreadyInSet(address _rollup) external whenCallerIsOwner {
    // it should add the rollup to state
    // it should emit a {InstanceAdded} event
    vm.assume(_rollup != address(0xdead));

    {
      DataStructures.RegistrySnapshot memory snapshotBefore = registry.getCurrentSnapshot();
      assertEq(snapshotBefore.blockNumber, block.number);
      assertEq(snapshotBefore.rollup, address(0xdead));
      assertEq(registry.numberOfVersions(), 1);
    }

    vm.expectEmit(true, true, false, false, address(registry));
    emit IRegistry.InstanceAdded(_rollup, 1);
    registry.upgrade(_rollup);

    assertEq(registry.numberOfVersions(), 2);

    DataStructures.RegistrySnapshot memory snapshot = registry.getCurrentSnapshot();
    assertEq(snapshot.blockNumber, block.number);
    assertGt(snapshot.blockNumber, 0);
    assertEq(snapshot.rollup, _rollup);
  }
}
```
Rumata888 pushed a commit that referenced this issue Sep 27, 2024
Slight extension on #8818 to separate gov and instance more clearly. 

Gov does not have dependencies on core, but core can depend on the gov. 

Removes the registry value from the `Rollup` does not address that an
upgrade would make the fee contract unbacked, that is to be handled
separately in #8756.

Updates testing for the `Registry` contract to use the [Branching Tree
Technique](https://www.youtube.com/watch?v=0-EmbNVgFA4) from Paul. Found
it quite neat. If using `bulloak` as well quite convenient to build the
setups.

The TL;DR is, build a `.tree` file outlining the test for a function,
and then use `bulloak scaffold` to prepare a testing file and then fill
in the logic. Makes it quite nice to follow the logic.

# Example time

```.tree
UpgradeTest
├── when caller is not owner
│   └── it should revert
└── when caller is owner
    ├── when rollup already in set
    │   └── it should revert
    └── when rollup not already in set
        ├── it should add the rollup to state
        └── it should emit a {InstanceAdded} event
```

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.27;

import {Test} from "forge-std/Test.sol";

import {Registry} from "@aztec/governance/Registry.sol";

contract RegistryBase is Test {
  Registry internal registry;

  function setUp() public {
    registry = new Registry(address(this));
  }
}
```

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.27;

import {RegistryBase} from "./Base.t.sol";

import {Ownable} from "@oz/access/Ownable.sol";

import {IRegistry} from "@aztec/governance/interfaces/IRegistry.sol";
import {Errors} from "@aztec/governance/libraries/Errors.sol";
import {DataStructures} from "@aztec/governance/libraries/DataStructures.sol";

contract UpgradeTest is RegistryBase {
  function test_RevertWhen_CallerIsNotOwner(address _caller) external {
    // it should revert
    vm.assume(_caller != address(this));
    vm.prank(_caller);
    vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, _caller));
    registry.upgrade(address(uint160(uint256(bytes32("new instance")))));
  }

  modifier whenCallerIsOwner() {
    _;
  }

  function test_RevertWhen_RollupAlreadyInSet() external whenCallerIsOwner {
    // it should revert
    address rollup = registry.getRollup();

    vm.expectRevert(
      abi.encodeWithSelector(Errors.Registry__RollupAlreadyRegistered.selector, rollup)
    );
    registry.upgrade(rollup);
  }

  function test_WhenRollupNotAlreadyInSet(address _rollup) external whenCallerIsOwner {
    // it should add the rollup to state
    // it should emit a {InstanceAdded} event
    vm.assume(_rollup != address(0xdead));

    {
      DataStructures.RegistrySnapshot memory snapshotBefore = registry.getCurrentSnapshot();
      assertEq(snapshotBefore.blockNumber, block.number);
      assertEq(snapshotBefore.rollup, address(0xdead));
      assertEq(registry.numberOfVersions(), 1);
    }

    vm.expectEmit(true, true, false, false, address(registry));
    emit IRegistry.InstanceAdded(_rollup, 1);
    registry.upgrade(_rollup);

    assertEq(registry.numberOfVersions(), 2);

    DataStructures.RegistrySnapshot memory snapshot = registry.getCurrentSnapshot();
    assertEq(snapshot.blockNumber, block.number);
    assertGt(snapshot.blockNumber, 0);
    assertEq(snapshot.rollup, _rollup);
  }
}
```
Rumata888 pushed a commit that referenced this issue Sep 27, 2024
Slight extension on #8818 to separate gov and instance more clearly. 

Gov does not have dependencies on core, but core can depend on the gov. 

Removes the registry value from the `Rollup` does not address that an
upgrade would make the fee contract unbacked, that is to be handled
separately in #8756.

Updates testing for the `Registry` contract to use the [Branching Tree
Technique](https://www.youtube.com/watch?v=0-EmbNVgFA4) from Paul. Found
it quite neat. If using `bulloak` as well quite convenient to build the
setups.

The TL;DR is, build a `.tree` file outlining the test for a function,
and then use `bulloak scaffold` to prepare a testing file and then fill
in the logic. Makes it quite nice to follow the logic.

# Example time

```.tree
UpgradeTest
├── when caller is not owner
│   └── it should revert
└── when caller is owner
    ├── when rollup already in set
    │   └── it should revert
    └── when rollup not already in set
        ├── it should add the rollup to state
        └── it should emit a {InstanceAdded} event
```

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.27;

import {Test} from "forge-std/Test.sol";

import {Registry} from "@aztec/governance/Registry.sol";

contract RegistryBase is Test {
  Registry internal registry;

  function setUp() public {
    registry = new Registry(address(this));
  }
}
```

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.27;

import {RegistryBase} from "./Base.t.sol";

import {Ownable} from "@oz/access/Ownable.sol";

import {IRegistry} from "@aztec/governance/interfaces/IRegistry.sol";
import {Errors} from "@aztec/governance/libraries/Errors.sol";
import {DataStructures} from "@aztec/governance/libraries/DataStructures.sol";

contract UpgradeTest is RegistryBase {
  function test_RevertWhen_CallerIsNotOwner(address _caller) external {
    // it should revert
    vm.assume(_caller != address(this));
    vm.prank(_caller);
    vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, _caller));
    registry.upgrade(address(uint160(uint256(bytes32("new instance")))));
  }

  modifier whenCallerIsOwner() {
    _;
  }

  function test_RevertWhen_RollupAlreadyInSet() external whenCallerIsOwner {
    // it should revert
    address rollup = registry.getRollup();

    vm.expectRevert(
      abi.encodeWithSelector(Errors.Registry__RollupAlreadyRegistered.selector, rollup)
    );
    registry.upgrade(rollup);
  }

  function test_WhenRollupNotAlreadyInSet(address _rollup) external whenCallerIsOwner {
    // it should add the rollup to state
    // it should emit a {InstanceAdded} event
    vm.assume(_rollup != address(0xdead));

    {
      DataStructures.RegistrySnapshot memory snapshotBefore = registry.getCurrentSnapshot();
      assertEq(snapshotBefore.blockNumber, block.number);
      assertEq(snapshotBefore.rollup, address(0xdead));
      assertEq(registry.numberOfVersions(), 1);
    }

    vm.expectEmit(true, true, false, false, address(registry));
    emit IRegistry.InstanceAdded(_rollup, 1);
    registry.upgrade(_rollup);

    assertEq(registry.numberOfVersions(), 2);

    DataStructures.RegistrySnapshot memory snapshot = registry.getCurrentSnapshot();
    assertEq(snapshot.blockNumber, block.number);
    assertGt(snapshot.blockNumber, 0);
    assertEq(snapshot.rollup, _rollup);
  }
}
```
@LHerskind LHerskind self-assigned this Oct 23, 2024
@LHerskind
Copy link
Contributor Author

The initial variation of this is handled by #7938, so will be closing this for now.

@github-project-automation github-project-automation bot moved this from Todo to Done in A3 Oct 24, 2024
@iAmMichaelConnor iAmMichaelConnor removed this from A3 Oct 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant