Skip to content

Commit 8212fb2

Browse files
authored
Merge pull request #349 from rsksmart/feature/GBI-2808
Feature/GBI-2808 - PegOut Contract implementation
2 parents 83b1eb7 + f1fd36f commit 8212fb2

25 files changed

+2608
-29
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,7 @@
33
name: CI
44

55
# Controls when the workflow will run
6-
on:
7-
push:
8-
branches: [master, Stable-Test, QA-Test]
9-
pull_request:
10-
11-
# Allows you to run this workflow manually from the Actions tab
12-
workflow_dispatch:
6+
on: [push, pull_request, workflow_dispatch]
137

148
permissions:
159
contents: read

.github/workflows/slither.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
sarif: results.sarif
3434
fail-on: none
3535
target: .
36-
slither-args: --filter-paths "node_modules/|contracts/test-contracts/safe-test-contracts/"
36+
slither-args: --filter-paths "node_modules/|contracts/test-contracts/safe-test-contracts/|contracts/legacy"
3737
- name: Upload SARIF file
3838
uses: github/codeql-action/upload-sarif@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0
3939
with:

contracts/DaoContributor.sol

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity 0.8.25;
3+
4+
import {
5+
OwnableUpgradeable
6+
} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
7+
import {
8+
ReentrancyGuardUpgradeable
9+
} from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
10+
import {Flyover} from "./libraries/Flyover.sol";
11+
12+
/// @title OwnableDaoContributorUpgradeable
13+
/// @notice This contract is used to handle the contributions to the DAO
14+
/// @author Rootstock Labs
15+
/// @dev Any contract that inherits from this contract will be able to collect DAO
16+
/// contributions according to the logic the child contract defines
17+
abstract contract OwnableDaoContributorUpgradeable is
18+
ReentrancyGuardUpgradeable,
19+
OwnableUpgradeable {
20+
21+
// @custom:storage-location erc7201:rsk.dao.contributor
22+
struct DaoContributorStorage {
23+
uint256 feePercentage;
24+
uint256 currentContribution;
25+
address payable feeCollector;
26+
}
27+
28+
// keccak256(abi.encode(uint256(keccak256(bytes("rsk.dao.contributor"))) - 1)) & ~bytes32(uint256(0xff));
29+
bytes32 private constant _CONTRIBUTOR_STORAGE_LOCATION =
30+
0xb7e513d124139aa68259a99d4c2c344f3ba61e36716330d77f7fa887d0048e00;
31+
32+
/// @notice This event is emitted when a contribution is made to the DAO
33+
/// @param contributor the address of the contributor
34+
/// @param amount the amount of the contribution
35+
event DaoContribution(address indexed contributor, uint256 indexed amount);
36+
37+
/// @notice This event is emitted when the DAO fees are claimed. The claim is always all the
38+
/// contributions made to the DAO by this contract so far
39+
/// @param claimer the address of the claimer
40+
/// @param receiver the address of the receiver
41+
/// @param amount the amount of the fees claimed
42+
event DaoFeesClaimed(address indexed claimer, address indexed receiver, uint256 indexed amount);
43+
44+
/// @notice This event is emitted when the contributions are configured
45+
/// @param feeCollector the address of the fee collector
46+
/// @param feePercentage the percentage of the contributions that goes to the DAO
47+
event ContributionsConfigured(address indexed feeCollector, uint256 indexed feePercentage);
48+
49+
/// @notice This error is emitted when there are no fees to claim
50+
error NoFees();
51+
52+
/// @notice This error is emitted when the fee collector is not set
53+
error FeeCollectorUnset();
54+
55+
/// @notice This function is used to claim the contributions to the DAO.
56+
/// It sends to the fee collector all the accumulated contributions so far
57+
/// and resets the accumulated contributions to zero
58+
/// @dev The function is only callable by the owner of the contract
59+
function claimContribution() external onlyOwner nonReentrant {
60+
DaoContributorStorage storage $ = _getContributorStorage();
61+
uint256 amount = $.currentContribution;
62+
$.currentContribution = 0;
63+
address feeCollector = $.feeCollector;
64+
if (amount == 0) revert NoFees();
65+
if (feeCollector == address(0)) revert FeeCollectorUnset();
66+
if (amount > address(this).balance) revert Flyover.NoBalance(amount, address(this).balance);
67+
emit DaoFeesClaimed(msg.sender, feeCollector, amount);
68+
(bool sent, bytes memory reason) = feeCollector.call{value: amount}("");
69+
if (!sent) revert Flyover.PaymentFailed(feeCollector, amount, reason);
70+
}
71+
72+
/// @notice This function is used to configure the contributions to the DAO
73+
/// @param feeCollector the address of the fee collector
74+
/// @param feePercentage the percentage of the contributions that goes to the DAO
75+
/// @dev The function is only callable by the owner of the contract
76+
function configureContributions(
77+
address payable feeCollector,
78+
uint256 feePercentage
79+
) external onlyOwner {
80+
DaoContributorStorage storage $ = _getContributorStorage();
81+
$.feeCollector = feeCollector;
82+
$.feePercentage = feePercentage;
83+
emit ContributionsConfigured(feeCollector, feePercentage);
84+
}
85+
86+
/// @notice This function is used to get the fee percentage
87+
/// that the child contracts use to calculate the contributions
88+
/// @return feePercentage the fee percentage
89+
function getFeePercentage() external view returns (uint256) {
90+
return _getContributorStorage().feePercentage;
91+
}
92+
93+
/// @notice This function is used to get the current contribution
94+
/// @return currentContribution the current contribution
95+
function getCurrentContribution() external view returns (uint256) {
96+
return _getContributorStorage().currentContribution;
97+
}
98+
99+
/// @notice This function is used to get the fee collector
100+
/// @return feeCollector the fee collector address
101+
function getFeeCollector() external view returns (address) {
102+
return _getContributorStorage().feeCollector;
103+
}
104+
105+
/// @notice This function is used to initialize the contract
106+
/// @param owner the owner of the contract
107+
/// @param feePercentage the percentage that the child contracts use to calculate the contributions
108+
/// @param feeCollector the address of the fee collector that will receive the contributions
109+
// solhint-disable-next-line func-name-mixedcase
110+
function __OwnableDaoContributor_init(
111+
address owner,
112+
uint256 feePercentage,
113+
address payable feeCollector
114+
) internal onlyInitializing {
115+
__ReentrancyGuard_init_unchained();
116+
__Ownable_init_unchained(owner);
117+
DaoContributorStorage storage $ = _getContributorStorage();
118+
$.feePercentage = feePercentage;
119+
$.feeCollector = feeCollector;
120+
}
121+
122+
/// @notice This function is used to add a contribution to the DAO
123+
/// @dev The function is only callable by the child contract, it can be
124+
/// included wherever they consider the protocol should collect fees for the DAO
125+
/// @param contributor the address of the contributor
126+
/// @param amount the amount of the contribution
127+
function _addDaoContribution(address contributor, uint256 amount) internal {
128+
if (amount < 1) return;
129+
DaoContributorStorage storage $ = _getContributorStorage();
130+
$.currentContribution += amount;
131+
emit DaoContribution(contributor, amount);
132+
}
133+
134+
/// @dev The function is used to get the storage of the contract, avoid using the regular
135+
/// storage to prevent conflicts with state variables of the child contract
136+
/// @return $ the contributor storage
137+
function _getContributorStorage() private pure returns (DaoContributorStorage storage $) {
138+
assembly {
139+
$.slot := _CONTRIBUTOR_STORAGE_LOCATION
140+
}
141+
}
142+
}

0 commit comments

Comments
 (0)