Skip to content

Commit ff232fc

Browse files
committed
feat: sysstia
1 parent 525fefe commit ff232fc

File tree

6 files changed

+137
-0
lines changed

6 files changed

+137
-0
lines changed
+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// Copyright 2023 Aztec Labs.
3+
pragma solidity >=0.8.27;
4+
5+
import {IERC20} from "@oz/token/ERC20/IERC20.sol";
6+
import {SafeERC20} from "@oz/token/ERC20/utils/SafeERC20.sol";
7+
8+
import {IRegistry} from "@aztec/governance/interfaces/IRegistry.sol";
9+
import {ISysstia} from "@aztec/governance/interfaces/ISysstia.sol";
10+
11+
import {Errors} from "@aztec/governance/libraries/Errors.sol";
12+
13+
contract Sysstia is ISysstia {
14+
using SafeERC20 for IERC20;
15+
16+
// This value is pulled out my ass. Don't take it seriously
17+
uint256 public constant BLOCK_REWARD = 50e18;
18+
19+
IERC20 public immutable TST;
20+
IRegistry public immutable REGISTRY;
21+
22+
constructor(IERC20 _tst, IRegistry _registry) {
23+
TST = _tst;
24+
REGISTRY = _registry;
25+
}
26+
27+
/**
28+
* @notice Simple claim of a block reward
29+
* Note especially that it can be called any number of times.
30+
* Essentially a placeholder until more nuanced logic is designed.
31+
*
32+
* @dev Does not check if the tokens are actually available first.
33+
*
34+
* @param _to - The address to receive the reward
35+
*
36+
* @return - the amount claimed
37+
*/
38+
function claim(address _to) external override(ISysstia) returns (uint256) {
39+
address canonical = REGISTRY.getRollup();
40+
require(msg.sender == canonical, Errors.Sysstia__InvalidCaller(msg.sender, canonical));
41+
TST.safeTransfer(_to, BLOCK_REWARD);
42+
return BLOCK_REWARD;
43+
}
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
pragma solidity >=0.8.27;
3+
4+
interface ISysstia {
5+
function claim(address _to) external returns (uint256);
6+
}

l1-contracts/src/governance/libraries/Errors.sol

+2
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,6 @@ library Errors {
1515

1616
error Registry__RollupAlreadyRegistered(address rollup); // 0x3c34eabf
1717
error Registry__RollupNotRegistered(address rollup); // 0xa1fee4cf
18+
19+
error Sysstia__InvalidCaller(address caller, address canonical); // 0xb95e39f6
1820
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity >=0.8.27;
3+
4+
import {Test} from "forge-std/Test.sol";
5+
6+
import {IMintableERC20} from "@aztec/governance/interfaces/IMintableERC20.sol";
7+
8+
import {Registry} from "@aztec/governance/Registry.sol";
9+
import {Sysstia} from "@aztec/governance/Sysstia.sol";
10+
11+
import {TestERC20} from "@aztec/mock/TestERC20.sol";
12+
13+
contract SysstiaBase is Test {
14+
IMintableERC20 internal token;
15+
Registry internal registry;
16+
Sysstia internal sysstia;
17+
18+
function setUp() public {
19+
token = IMintableERC20(address(new TestERC20()));
20+
registry = new Registry(address(this));
21+
sysstia = new Sysstia(token, registry);
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity >=0.8.27;
3+
4+
import {SysstiaBase} from "./Base.t.sol";
5+
6+
import {IERC20Errors} from "@oz/interfaces/draft-IERC6093.sol";
7+
8+
import {Errors} from "@aztec/governance/libraries/Errors.sol";
9+
10+
contract ClaimTest is SysstiaBase {
11+
address internal caller;
12+
13+
function test_WhenCallerIsNotCanonical(address _caller) external {
14+
// it reverts
15+
vm.assume(_caller != address(0xdead));
16+
17+
vm.expectRevert(
18+
abi.encodeWithSelector(Errors.Sysstia__InvalidCaller.selector, _caller, address(0xdead))
19+
);
20+
vm.prank(_caller);
21+
sysstia.claim(_caller);
22+
}
23+
24+
modifier whenCallerIsCanonical() {
25+
caller = address(0xdead);
26+
_;
27+
}
28+
29+
function test_GivenBalanceSmallerThanReward() external whenCallerIsCanonical {
30+
// it reverts
31+
uint256 needed = sysstia.BLOCK_REWARD();
32+
vm.prank(caller);
33+
vm.expectRevert(
34+
abi.encodeWithSelector(
35+
IERC20Errors.ERC20InsufficientBalance.selector, address(sysstia), 0, needed
36+
)
37+
);
38+
sysstia.claim(caller);
39+
}
40+
41+
function test_GivenBalanceLargerOrEqualReward(uint256 _balance) external whenCallerIsCanonical {
42+
// it transfers block reward of asset
43+
// it returns block reward value
44+
uint256 balance = bound(_balance, sysstia.BLOCK_REWARD(), type(uint256).max);
45+
token.mint(address(sysstia), balance);
46+
47+
uint256 callerBalance = token.balanceOf(caller);
48+
vm.prank(caller);
49+
sysstia.claim(caller);
50+
51+
assertEq(token.balanceOf(caller), callerBalance + sysstia.BLOCK_REWARD());
52+
}
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
ClaimTest
2+
├── when caller is not canonical
3+
│ └── it reverts
4+
└── when caller is canonical
5+
├── given balance smaller than reward
6+
│ └── it reverts
7+
└── given balance larger or equal reward
8+
├── it transfers block reward of asset
9+
└── it returns block reward value

0 commit comments

Comments
 (0)