Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 54 additions & 54 deletions l1-contracts/gas_report.md

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions l1-contracts/src/core/RollupCore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ contract RollupCore is
CheatLib.setProtocolContractTreeRoot(_protocolContractTreeRoot);
}

function updateManaTarget(uint256 _manaTarget) external override(ITestRollup) onlyOwner {
FeeLib.updateManaTarget(_manaTarget);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have an event here. We have been pretty bad generally at adding events when state change, but it is usually good practice since it makes analysis and such much simpler.

emit ITestRollup.ManaTargetUpdated(_manaTarget);
}

/* -------------------------------------------------------------------------- */
/* CHEAT CODES END HERE */
/* -------------------------------------------------------------------------- */
Expand Down
3 changes: 3 additions & 0 deletions l1-contracts/src/core/interfaces/IRollup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,13 @@ struct CheatDepositArgs {
}

interface ITestRollup {
event ManaTargetUpdated(uint256 indexed manaTarget);

function setEpochVerifier(address _verifier) external;
function setVkTreeRoot(bytes32 _vkTreeRoot) external;
function setProtocolContractTreeRoot(bytes32 _protocolContractTreeRoot) external;
function cheat__InitialiseValidatorSet(CheatDepositArgs[] memory _args) external;
function updateManaTarget(uint256 _manaTarget) external;
}

interface IRollupCore {
Expand Down
7 changes: 7 additions & 0 deletions l1-contracts/src/core/libraries/rollup/FeeLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,13 @@ library FeeLib {
});
}

function updateManaTarget(uint256 _manaTarget) internal {
FeeStore storage feeStore = getStorage();
feeStore.manaTarget = _manaTarget;
feeStore.congestionUpdateFraction =
_manaTarget * MAGIC_CONGESTION_VALUE_MULTIPLIER / MAGIC_CONGESTION_VALUE_DIVISOR;
}

function writeFeeHeader(
uint256 _blockNumber,
int256 _feeAssetPriceModifier,
Expand Down
7 changes: 7 additions & 0 deletions l1-contracts/src/governance/interfaces/IMintableERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,12 @@ pragma solidity >=0.8.27;
import {IERC20} from "@oz/token/ERC20/IERC20.sol";

interface IMintableERC20 is IERC20 {
event MinterAdded(address indexed minter);
event MinterRemoved(address indexed minter);

error NotMinter(address caller);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🫡


function mint(address _to, uint256 _amount) external;
function addMinter(address _minter) external;
function removeMinter(address _minter) external;
}
31 changes: 31 additions & 0 deletions l1-contracts/src/mock/FeeAssetHandler.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.27;

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

interface IFeeAssetHandler {
event MintAmountSet(uint256 amount);

function mint(address _recipient) external;
function setMintAmount(uint256 _amount) external;
}

contract FeeAssetHandler is IFeeAssetHandler, Ownable {
IMintableERC20 public immutable FEE_ASSET;
uint256 public mintAmount;

constructor(address _owner, address _feeAsset, uint256 _mintAmount) Ownable(_owner) {
FEE_ASSET = IMintableERC20(_feeAsset);
mintAmount = _mintAmount;
}

function mint(address _recipient) external override {
FEE_ASSET.mint(_recipient, mintAmount);
}

function setMintAmount(uint256 _amount) external override onlyOwner {
mintAmount = _amount;
emit MintAmountSet(_amount);
}
}
37 changes: 26 additions & 11 deletions l1-contracts/src/mock/TestERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,42 @@ import {ERC20} from "@oz/token/ERC20/ERC20.sol";
import {IMintableERC20} from "./../governance/interfaces/IMintableERC20.sol";

contract TestERC20 is ERC20, IMintableERC20, Ownable {
bool public freeForAll = false;
mapping(address => bool) public minters;

modifier ownerOrFreeForAll() {
if (msg.sender != owner() && !freeForAll) {
revert("Not owner or free for all");
}
modifier onlyMinter() {
require(minters[msg.sender], NotMinter(msg.sender));
_;
}

constructor(string memory _name, string memory _symbol, address _owner)
ERC20(_name, _symbol)
Ownable(_owner)
{}

// solhint-disable-next-line comprehensive-interface
function setFreeForAll(bool _freeForAll) external onlyOwner {
freeForAll = _freeForAll;
{
minters[_owner] = true;
emit MinterAdded(_owner);
}

function mint(address _to, uint256 _amount) external override(IMintableERC20) ownerOrFreeForAll {
function mint(address _to, uint256 _amount) external override(IMintableERC20) onlyMinter {
_mint(_to, _amount);
}

function addMinter(address _minter) public override(IMintableERC20) onlyOwner {
minters[_minter] = true;
emit MinterAdded(_minter);
}

function removeMinter(address _minter) public override(IMintableERC20) onlyOwner {
minters[_minter] = false;
emit MinterRemoved(_minter);
}

function transferOwnership(address newOwner) public override(Ownable) onlyOwner {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Micronit, but arg should be _newOwner.

if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
removeMinter(owner());
addMinter(newOwner);
_transferOwnership(newOwner);
}
}
// docs:end:contract
24 changes: 0 additions & 24 deletions l1-contracts/test/TestERC20.t.sol

This file was deleted.

20 changes: 20 additions & 0 deletions l1-contracts/test/fee_asset_handler/base.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.27;

import {Test} from "forge-std/Test.sol";
import {TestERC20} from "@aztec/mock/TestERC20.sol";
import {FeeAssetHandler} from "@aztec/mock/FeeAssetHandler.sol";

// solhint-disable comprehensive-interface
// solhint-disable func-name-mixedcase

contract FeeAssetHandlerTestBase is Test {
TestERC20 internal testERC20;
FeeAssetHandler internal feeAssetHandler;

function setUp() external {
testERC20 = new TestERC20("test", "TEST", address(this));
feeAssetHandler = new FeeAssetHandler(address(this), address(testERC20), 100);
testERC20.addMinter(address(feeAssetHandler));
}
}
21 changes: 21 additions & 0 deletions l1-contracts/test/fee_asset_handler/mint.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.27;

import {IERC20} from "@oz/token/ERC20/ERC20.sol";
import {FeeAssetHandlerTestBase} from "./base.t.sol";

// solhint-disable comprehensive-interface
// solhint-disable func-name-mixedcase

contract MintTest is FeeAssetHandlerTestBase {
function test_WhenAnyoneCallsMint(address _caller, address _recipient) external {
// it mints the mint amount to the recipient
// it emits {Minted} event
vm.assume(_recipient != address(0));
vm.expectEmit(true, true, true, true, address(testERC20));
emit IERC20.Transfer(address(0), _recipient, feeAssetHandler.mintAmount());
vm.prank(_caller);
feeAssetHandler.mint(_recipient);
assertEq(testERC20.balanceOf(_recipient), feeAssetHandler.mintAmount());
}
}
4 changes: 4 additions & 0 deletions l1-contracts/test/fee_asset_handler/mint.tree
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
MintTest
└── when anyone calls mint
├── it mints the mint amount to the recipient
└── it emits {Minted} event
28 changes: 28 additions & 0 deletions l1-contracts/test/fee_asset_handler/setMintAmount.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.27;

import {IFeeAssetHandler} from "@aztec/mock/FeeAssetHandler.sol";
import {Ownable} from "@oz/access/Ownable.sol";
import {FeeAssetHandlerTestBase} from "./base.t.sol";

// solhint-disable comprehensive-interface
// solhint-disable func-name-mixedcase

contract SetMintAmountTest is FeeAssetHandlerTestBase {
function test_WhenCallerIsNotOwner(address _caller, uint256 _mintAmount) external {
// it reverts
vm.assume(_caller != feeAssetHandler.owner());
vm.prank(_caller);
vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, _caller));
feeAssetHandler.setMintAmount(_mintAmount);
}

function test_WhenCallerIsOwner(uint256 _mintAmount) external {
// it updates the mint amount
// it emits {MintAmountUpdated} event
vm.expectEmit(true, true, true, true, address(feeAssetHandler));
emit IFeeAssetHandler.MintAmountSet(_mintAmount);
feeAssetHandler.setMintAmount(_mintAmount);
assertEq(feeAssetHandler.mintAmount(), _mintAmount);
}
}
6 changes: 6 additions & 0 deletions l1-contracts/test/fee_asset_handler/setMintAmount.tree
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
SetMintAmountTest
├── when caller is not owner
│ └── it reverts
└── when caller is owner
├── it updates the mint amount
└── it emits {MintAmountUpdated} event
42 changes: 42 additions & 0 deletions l1-contracts/test/test_erc20/addMinter.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.27;

import {IMintableERC20} from "@aztec/governance/interfaces/IMintableERC20.sol";
import {Ownable} from "@oz/access/Ownable.sol";
import {TestERC20TestBase} from "./base.t.sol";

// solhint-disable comprehensive-interface
// solhint-disable func-name-mixedcase

contract AddMinterTest is TestERC20TestBase {
modifier whenTheCallerIsTheOwner() {
vm.startPrank(testERC20.owner());
_;
vm.stopPrank();
}

modifier whenTheCallerIsNotTheOwner(address _caller) {
vm.assume(_caller != testERC20.owner());
vm.startPrank(_caller);
_;
vm.stopPrank();
}

function test_WhenTheCallerIsNotTheOwner(address _caller, address _minter)
external
whenTheCallerIsNotTheOwner(_caller)
{
// it reverts
vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, _caller));
testERC20.addMinter(_minter);
}

function test_WhenTheCallerIsTheOwner(address _minter) external whenTheCallerIsTheOwner {
// it adds the minter
// it emits a MinterAdded event
vm.expectEmit(true, true, true, true, address(testERC20));
emit IMintableERC20.MinterAdded(_minter);
testERC20.addMinter(_minter);
assertEq(testERC20.minters(_minter), true);
}
}
6 changes: 6 additions & 0 deletions l1-contracts/test/test_erc20/addMinter.tree
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
AddMinterTest
├── when the caller is not the owner
│ └── it reverts
└── when the caller is the owner
├── it adds the minter
└── it emits a MinterAdded event
17 changes: 17 additions & 0 deletions l1-contracts/test/test_erc20/base.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.27;

import {Test} from "forge-std/Test.sol";
import {TestERC20} from "@aztec/mock/TestERC20.sol";

// solhint-disable comprehensive-interface
// solhint-disable func-name-mixedcase

contract TestERC20TestBase is Test {
// solhint-disable private-vars-leading-underscore
TestERC20 internal testERC20;

function setUp() external {
testERC20 = new TestERC20("test", "TEST", address(this));
}
}
34 changes: 34 additions & 0 deletions l1-contracts/test/test_erc20/mint.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.27;

import {IMintableERC20} from "@aztec/governance/interfaces/IMintableERC20.sol";
import {IERC20} from "@oz/token/ERC20/IERC20.sol";
import {TestERC20TestBase} from "./base.t.sol";

// solhint-disable comprehensive-interface
// solhint-disable func-name-mixedcase

contract MintTest is TestERC20TestBase {
function test_WhenTheCallerIsNotAMinter(address _caller, address _to, uint256 _amount) external {
vm.assume(_caller != testERC20.owner());
vm.startPrank(_caller);
// it reverts
vm.expectRevert(abi.encodeWithSelector(IMintableERC20.NotMinter.selector, _caller));
testERC20.mint(_to, _amount);
vm.stopPrank();
}

function test_WhenTheCallerIsAMinter(address _caller, address _to, uint256 _amount) external {
// it mints the amount to _to
// it emits a Transfer event
vm.prank(testERC20.owner());
testERC20.addMinter(_caller);

vm.assume(_to != address(0));

vm.prank(_caller);
vm.expectEmit(true, true, true, true, address(testERC20));
emit IERC20.Transfer(address(0), _to, _amount);
testERC20.mint(_to, _amount);
}
}
6 changes: 6 additions & 0 deletions l1-contracts/test/test_erc20/mint.tree
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
MintTest
├── when the caller is not a minter
│ └── it reverts
└── when the caller is a minter
├── it mints the amount to _to
└── it emits a Transfer event
Loading