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

feat: sysstia #8941

Merged
merged 1 commit into from
Oct 11, 2024
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
44 changes: 44 additions & 0 deletions l1-contracts/src/governance/Sysstia.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2023 Aztec Labs.
pragma solidity >=0.8.27;

import {IERC20} from "@oz/token/ERC20/IERC20.sol";
import {SafeERC20} from "@oz/token/ERC20/utils/SafeERC20.sol";

import {IRegistry} from "@aztec/governance/interfaces/IRegistry.sol";
import {ISysstia} from "@aztec/governance/interfaces/ISysstia.sol";

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

contract Sysstia is ISysstia {
using SafeERC20 for IERC20;

// This value is pulled out my ass. Don't take it seriously
Copy link
Member

Choose a reason for hiding this comment

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

image

uint256 public constant BLOCK_REWARD = 50e18;

IERC20 public immutable TST;
IRegistry public immutable REGISTRY;

constructor(IERC20 _tst, IRegistry _registry) {
TST = _tst;
REGISTRY = _registry;
}

/**
* @notice Simple claim of a block reward
* Note especially that it can be called any number of times.
* Essentially a placeholder until more nuanced logic is designed.
*
* @dev Does not check if the tokens are actually available first.
*
* @param _to - The address to receive the reward
*
* @return - the amount claimed
*/
function claim(address _to) external override(ISysstia) returns (uint256) {
address canonical = REGISTRY.getRollup();
require(msg.sender == canonical, Errors.Sysstia__InvalidCaller(msg.sender, canonical));
TST.safeTransfer(_to, BLOCK_REWARD);
return BLOCK_REWARD;
}
}
6 changes: 6 additions & 0 deletions l1-contracts/src/governance/interfaces/ISysstia.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.27;

interface ISysstia {
function claim(address _to) external returns (uint256);
}
2 changes: 2 additions & 0 deletions l1-contracts/src/governance/libraries/Errors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ library Errors {

error Registry__RollupAlreadyRegistered(address rollup); // 0x3c34eabf
error Registry__RollupNotRegistered(address rollup); // 0xa1fee4cf

error Sysstia__InvalidCaller(address caller, address canonical); // 0xb95e39f6
}
23 changes: 23 additions & 0 deletions l1-contracts/test/governance/sysstia/Base.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.27;

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

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

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

import {TestERC20} from "@aztec/mock/TestERC20.sol";

contract SysstiaBase is Test {
IMintableERC20 internal token;
Registry internal registry;
Sysstia internal sysstia;

function setUp() public {
token = IMintableERC20(address(new TestERC20()));
registry = new Registry(address(this));
sysstia = new Sysstia(token, registry);
}
}
53 changes: 53 additions & 0 deletions l1-contracts/test/governance/sysstia/claim.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.27;

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

import {IERC20Errors} from "@oz/interfaces/draft-IERC6093.sol";

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

contract ClaimTest is SysstiaBase {
address internal caller;

function test_WhenCallerIsNotCanonical(address _caller) external {
// it reverts
vm.assume(_caller != address(0xdead));

vm.expectRevert(
abi.encodeWithSelector(Errors.Sysstia__InvalidCaller.selector, _caller, address(0xdead))
);
vm.prank(_caller);
sysstia.claim(_caller);
}

modifier whenCallerIsCanonical() {
caller = address(0xdead);
_;
}

function test_GivenBalanceSmallerThanReward() external whenCallerIsCanonical {
// it reverts
uint256 needed = sysstia.BLOCK_REWARD();
vm.prank(caller);
vm.expectRevert(
abi.encodeWithSelector(
IERC20Errors.ERC20InsufficientBalance.selector, address(sysstia), 0, needed
)
);
sysstia.claim(caller);
}

function test_GivenBalanceLargerOrEqualReward(uint256 _balance) external whenCallerIsCanonical {
// it transfers block reward of asset
// it returns block reward value
uint256 balance = bound(_balance, sysstia.BLOCK_REWARD(), type(uint256).max);
token.mint(address(sysstia), balance);

uint256 callerBalance = token.balanceOf(caller);
vm.prank(caller);
sysstia.claim(caller);

assertEq(token.balanceOf(caller), callerBalance + sysstia.BLOCK_REWARD());
}
}
9 changes: 9 additions & 0 deletions l1-contracts/test/governance/sysstia/claim.tree
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
ClaimTest
├── when caller is not canonical
│ └── it reverts
└── when caller is canonical
├── given balance smaller than reward
│ └── it reverts
└── given balance larger or equal reward
├── it transfers block reward of asset
└── it returns block reward value
Loading