Skip to content

Commit 77fedd0

Browse files
committed
fix: address 142
1 parent 80a24dc commit 77fedd0

File tree

5 files changed

+62
-0
lines changed

5 files changed

+62
-0
lines changed

l1-contracts/src/governance/RewardDistributor.sol

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ pragma solidity >=0.8.27;
55
import {IRegistry} from "@aztec/governance/interfaces/IRegistry.sol";
66
import {IRewardDistributor} from "@aztec/governance/interfaces/IRewardDistributor.sol";
77
import {Errors} from "@aztec/governance/libraries/Errors.sol";
8+
import {Ownable} from "@oz/access/Ownable.sol";
89
import {IERC20} from "@oz/token/ERC20/IERC20.sol";
910
import {SafeERC20} from "@oz/token/ERC20/utils/SafeERC20.sol";
1011

@@ -28,6 +29,12 @@ contract RewardDistributor is IRewardDistributor {
2829
ASSET.safeTransfer(_to, _amount);
2930
}
3031

32+
function recover(address _asset, address _to, uint256 _amount) external override(IRewardDistributor) {
33+
address owner = Ownable(address(REGISTRY)).owner();
34+
require(msg.sender == owner, Errors.RewardDistributor__InvalidCaller(msg.sender, owner));
35+
IERC20(_asset).safeTransfer(_to, _amount);
36+
}
37+
3138
function canonicalRollup() public view override(IRewardDistributor) returns (address) {
3239
return address(REGISTRY.getCanonicalRollup());
3340
}

l1-contracts/src/governance/interfaces/IRewardDistributor.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ pragma solidity >=0.8.27;
33

44
interface IRewardDistributor {
55
function claim(address _to, uint256 _amount) external;
6+
function recover(address _asset, address _to, uint256 _amount) external;
67
function canonicalRollup() external view returns (address);
78
}

l1-contracts/test/benchmark/happy.t.sol

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ contract FakeCanonical is IRewardDistributor {
9595
}
9696

9797
function updateRegistry(IRegistry _registry) external {}
98+
99+
function recover(address _asset, address _to, uint256 _amount) external {}
98100
}
99101

100102
contract BenchmarkRollupTest is FeeModelTestPoints, DecoderBase {

l1-contracts/test/compression/PreHeating.t.sol

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ contract FakeCanonical is IRewardDistributor {
9292
}
9393

9494
function updateRegistry(IRegistry _registry) external {}
95+
96+
function recover(address _asset, address _to, uint256 _amount) external {}
9597
}
9698

9799
/**
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity >=0.8.27;
3+
4+
import {RewardDistributorBase} from "./Base.t.sol";
5+
6+
import {Errors} from "@aztec/governance/libraries/Errors.sol";
7+
import {Ownable} from "@oz/access/Ownable.sol";
8+
import {TestERC20} from "@aztec/mock/TestERC20.sol";
9+
10+
contract RecoverTest is RewardDistributorBase {
11+
address internal caller;
12+
13+
function test_WhenCallerIsNotOwner(address _caller) external {
14+
// it reverts
15+
address owner = Ownable(address(registry)).owner();
16+
vm.assume(_caller != owner);
17+
18+
vm.expectRevert(abi.encodeWithSelector(Errors.RewardDistributor__InvalidCaller.selector, _caller, owner));
19+
vm.prank(_caller);
20+
rewardDistributor.recover(address(token), _caller, 1e18);
21+
}
22+
23+
modifier whenCallerIsOwner() {
24+
caller = Ownable(address(registry)).owner();
25+
_;
26+
}
27+
28+
function test_GivenBalanceGt0(uint256 _balance, uint256 _amount) external whenCallerIsOwner {
29+
// it transfers the requested amount
30+
31+
uint256 balance = bound(_balance, 1, type(uint256).max);
32+
uint256 amount = bound(_amount, 1, balance);
33+
token.mint(address(rewardDistributor), balance);
34+
35+
uint256 callerBalance = token.balanceOf(caller);
36+
vm.prank(caller);
37+
rewardDistributor.recover(address(token), caller, amount);
38+
39+
assertEq(token.balanceOf(caller), callerBalance + amount);
40+
assertEq(token.balanceOf(address(rewardDistributor)), balance - amount);
41+
42+
TestERC20 token2 = new TestERC20("Token2", "T2", address(this));
43+
token2.mint(address(rewardDistributor), balance);
44+
45+
vm.prank(caller);
46+
rewardDistributor.recover(address(token2), caller, amount);
47+
assertEq(token2.balanceOf(caller), amount);
48+
assertEq(token2.balanceOf(address(rewardDistributor)), balance - amount);
49+
}
50+
}

0 commit comments

Comments
 (0)