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

Fix linter warnings in the Disctributor #1112

Merged
merged 6 commits into from
Aug 29, 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
1 change: 1 addition & 0 deletions contracts/CommonErrors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ error GroupIndexIsInvalid(uint256 index);
error IsNotContract(address account);
error NotEnoughFunds();
error RoleRequired(bytes32 role);
error TokensTransferFailure();
98 changes: 51 additions & 47 deletions contracts/delegation/Distributor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,21 @@
along with SKALE Manager. If not, see <https://www.gnu.org/licenses/>.
*/

pragma solidity 0.8.17;

import {IERC1820Registry} from "@openzeppelin/contracts/utils/introspection/IERC1820Registry.sol";
import {IERC777Recipient} from "@openzeppelin/contracts/token/ERC777/IERC777Recipient.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

import {IDistributor} from "@skalenetwork/skale-manager-interfaces/delegation/IDistributor.sol";
import {
IValidatorService
} from "@skalenetwork/skale-manager-interfaces/delegation/IValidatorService.sol";
import {
IDelegationController
} from "@skalenetwork/skale-manager-interfaces/delegation/IDelegationController.sol";
import {ITimeHelpers} from "@skalenetwork/skale-manager-interfaces/delegation/ITimeHelpers.sol";

import {Permissions} from "../Permissions.sol";
import {ConstantsHolder} from "../ConstantsHolder.sol";
import {MathUtils} from "../utils/MathUtils.sol";
pragma solidity 0.8.26;

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IERC777Recipient } from "@openzeppelin/contracts/token/ERC777/IERC777Recipient.sol";
import { IERC1820Registry } from "@openzeppelin/contracts/utils/introspection/IERC1820Registry.sol";
import { IDelegationController }
from "@skalenetwork/skale-manager-interfaces/delegation/IDelegationController.sol";
import { IDistributor } from "@skalenetwork/skale-manager-interfaces/delegation/IDistributor.sol";
import { ITimeHelpers } from "@skalenetwork/skale-manager-interfaces/delegation/ITimeHelpers.sol";
import { IValidatorService }
from "@skalenetwork/skale-manager-interfaces/delegation/IValidatorService.sol";
import { IConstantsHolder } from "@skalenetwork/skale-manager-interfaces/IConstantsHolder.sol";
import { TokensTransferFailure } from "./../CommonErrors.sol";
import { Permissions } from "./../Permissions.sol";
import { MathUtils } from "./../utils/MathUtils.sol";

/**
* @title Distributor
Expand All @@ -48,15 +45,17 @@

IERC1820Registry private _erc1820;

// validatorId => month => token
mapping(uint256 => mapping(uint256 => uint256)) private _bountyPaid;
// validatorId => month => token
mapping(uint256 => mapping(uint256 => uint256)) private _feePaid;
// holder => validatorId => month
mapping(address => mapping(uint256 => uint256))
private _firstUnwithdrawnMonth;
// validatorId => month
mapping(uint256 => uint256) private _firstUnwithdrawnMonthForValidator;
mapping(uint256 validatorId => mapping(uint256 month => uint256 amount)) private _bountyPaid;
mapping(uint256 validatorId => mapping(uint256 month => uint256 amount)) private _feePaid;
mapping(
address holder => mapping(uint256 validatorId => uint256 month)
) private _firstUnwithdrawnMonth;
mapping(uint256 validatorId => uint256 month) private _firstUnwithdrawnMonthForValidator;

error BountyIsLocked();
error DataLengthIsIncorrect();
error FeeIsLocked();
error ReceiverIsIncorrect();

function initialize(address contractsAddress) public override initializer {
Permissions.initialize(contractsAddress);
Expand Down Expand Up @@ -91,18 +90,16 @@
ITimeHelpers timeHelpers = ITimeHelpers(
contractManager.getContract("TimeHelpers")
);
ConstantsHolder constantsHolder = ConstantsHolder(
IConstantsHolder constantsHolder = IConstantsHolder(
contractManager.getContract("ConstantsHolder")
);

require(
block.timestamp >=
timeHelpers.addMonths(
if (block.timestamp < timeHelpers.addMonths(
constantsHolder.launchTimestamp(),
constantsHolder.BOUNTY_LOCKUP_MONTHS()
),
"Bounty is locked"
);
)) {
revert BountyIsLocked();
}

uint256 bounty;
uint256 endMonth;
Expand All @@ -114,7 +111,9 @@
_firstUnwithdrawnMonth[msg.sender][validatorId] = endMonth;

IERC20 skaleToken = IERC20(contractManager.getContract("SkaleToken"));
require(skaleToken.transfer(to, bounty), "Failed to transfer tokens");
if(!skaleToken.transfer(to, bounty)) {
revert TokensTransferFailure();

Check warning on line 115 in contracts/delegation/Distributor.sol

View check run for this annotation

Codecov / codecov/patch

contracts/delegation/Distributor.sol#L115

Added line #L115 was not covered by tests
}

emit WithdrawBounty(msg.sender, validatorId, to, bounty);
}
Expand All @@ -137,18 +136,17 @@
ITimeHelpers timeHelpers = ITimeHelpers(
contractManager.getContract("TimeHelpers")
);
ConstantsHolder constantsHolder = ConstantsHolder(
IConstantsHolder constantsHolder = IConstantsHolder(
contractManager.getContract("ConstantsHolder")
);

require(
block.timestamp >=
timeHelpers.addMonths(
constantsHolder.launchTimestamp(),
constantsHolder.BOUNTY_LOCKUP_MONTHS()
),
"Fee is locked"
);
if (block.timestamp < timeHelpers.addMonths(
constantsHolder.launchTimestamp(),
constantsHolder.BOUNTY_LOCKUP_MONTHS()
)) {
revert FeeIsLocked();
}

// check Validator Exist inside getValidatorId
uint256 validatorId = validatorService.getValidatorId(msg.sender);

Expand All @@ -158,7 +156,9 @@

_firstUnwithdrawnMonthForValidator[validatorId] = endMonth;

require(skaleToken.transfer(to, fee), "Failed to transfer tokens");
if(!skaleToken.transfer(to, fee)) {
revert TokensTransferFailure();

Check warning on line 160 in contracts/delegation/Distributor.sol

View check run for this annotation

Codecov / codecov/patch

contracts/delegation/Distributor.sol#L160

Added line #L160 was not covered by tests
}

emit WithdrawFee(validatorId, to, fee);
}
Expand All @@ -171,8 +171,12 @@
bytes calldata userData,
bytes calldata
) external override allow("SkaleToken") {
require(to == address(this), "Receiver is incorrect");
require(userData.length == 32, "Data length is incorrect");
if (to != address(this)) {
revert ReceiverIsIncorrect();
}
if (userData.length != 32) {
revert DataLengthIsIncorrect();
}
DmytroNazarenko marked this conversation as resolved.
Show resolved Hide resolved
uint256 validatorId = abi.decode(userData, (uint256));
_distributeBounty(amount, validatorId);
}
Expand Down
25 changes: 25 additions & 0 deletions contracts/test/SkaleTokenInternalTester.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

pragma solidity 0.8.17;

import { IERC777Recipient } from "@openzeppelin/contracts/token/ERC777/IERC777Recipient.sol";
import { SkaleToken } from "../SkaleToken.sol";
import { ISkaleTokenInterfaceTester } from "./interfaces/ISkaleTokenInterfaceTester.sol";

Expand All @@ -32,6 +33,30 @@ contract SkaleTokenInternalTester is SkaleToken, ISkaleTokenInterfaceTester {
// solhint-disable-next-line no-empty-blocks
{ }

function callTokensReceived(
address implementer,
address operator,
address from,
address to,
uint256 amount,
bytes memory userData,
bytes memory operatorData
)
external
override
{
if (implementer != address(0)) {
IERC777Recipient(implementer).tokensReceived({
operator: operator,
from: from,
to: to,
amount: amount,
userData: userData,
operatorData: operatorData
});
}
}

function getMsgData() external view override returns (bytes memory msgData) {
return _msgData();
}
Expand Down
10 changes: 10 additions & 0 deletions contracts/test/interfaces/ISkaleTokenInterfaceTester.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,15 @@ pragma solidity 0.8.17;


interface ISkaleTokenInterfaceTester {
function callTokensReceived(
address implementer,
address operator,
address from,
address to,
uint256 amount,
bytes memory userData,
bytes memory operatorData
)
external;
function getMsgData() external view returns (bytes memory msgData);
}
2 changes: 1 addition & 1 deletion contracts/utils/MathUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
along with SKALE Manager. If not, see <https://www.gnu.org/licenses/>.
*/

pragma solidity 0.8.17;
pragma solidity ^0.8.17;


library MathUtils {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"@skalenetwork/ima-interfaces": "2.0.0-develop.67",
"@skalenetwork/marionette-interfaces": "^0.0.0-main.6",
"@skalenetwork/paymaster-interfaces": "^1.0.0-main.10",
"@skalenetwork/skale-manager-interfaces": "3.2.0-develop.0",
"@skalenetwork/skale-manager-interfaces": "3.2.0-develop.1",
"@skalenetwork/upgrade-tools": "^3.0.0-linter.42",
"@typechain/hardhat": "^9.1.0",
"dotenv": "^16.3.1",
Expand Down
28 changes: 26 additions & 2 deletions test/delegation/Delegation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,30 @@ describe("Delegation", () => {
.should.be.eventually.rejectedWith("Limit of validators is reached");
});

it("should revert on incorrect transfers", async () => {
const skaleTokenInternalTesterFactory = await ethers.getContractFactory("SkaleTokenInternalTester");
const skaleTokenInternalTester = await skaleTokenInternalTesterFactory.deploy(contractManager, []);
await contractManager.setContractsAddress("SkaleToken", skaleTokenInternalTester);
await skaleTokenInternalTester.callTokensReceived(
distributor,
ethers.ZeroAddress,
holder1,
holder2, // Receiver always needs to be the Distributor
5,
"0x",
"0x"
).should.be.revertedWithCustomError(distributor, "ReceiverIsIncorrect");
await skaleTokenInternalTester.callTokensReceived(
distributor,
ethers.ZeroAddress,
holder1,
distributor,
5,
"0x", // Data length always must be 32 bytes
"0x"
).should.be.revertedWithCustomError(distributor, "DataLengthIsIncorrect");
})

describe("when holders have tokens and validator is registered", () => {
let validatorId: bigint;
fastBeforeEach(async () => {
Expand Down Expand Up @@ -599,9 +623,9 @@ describe("Delegation", () => {
validatorId))[0].should.be.equal(31);

await distributor.connect(validator).withdrawFee(bountyAddress.address)
.should.be.eventually.rejectedWith("Fee is locked");
.should.be.revertedWithCustomError(distributor, "FeeIsLocked");
await distributor.connect(holder1).withdrawBounty(validatorId, bountyAddress.address)
.should.be.eventually.rejectedWith("Bounty is locked");
.should.be.revertedWithCustomError(distributor, "BountyIsLocked");

await nextMonth(contractManager, 3);

Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1741,10 +1741,10 @@
dependencies:
axios "^1.4.0"

"@skalenetwork/[email protected].0":
version "3.2.0-develop.0"
resolved "https://registry.yarnpkg.com/@skalenetwork/skale-manager-interfaces/-/skale-manager-interfaces-3.2.0-develop.0.tgz#01e64eeabf2b14b320074eb588b557bbd33bab39"
integrity sha512-f++aLtSwjLJgAb3dHAm/SMHvx2a0L3uWwF7aam1wCtB6YZrFLR3flzlH3Ms3JlLZtfl5iE7VBmsuidhAqpbfpw==
"@skalenetwork/[email protected].1":
version "3.2.0-develop.1"
resolved "https://registry.yarnpkg.com/@skalenetwork/skale-manager-interfaces/-/skale-manager-interfaces-3.2.0-develop.1.tgz#ec4ad8f2b4d12a5ff8d03763674a214be61c773d"
integrity sha512-ACugcMzRFa7nbHcJ8mZE/J60M8GW9gJKsqmQYEYoElzZBMTCstEeWy1ff6Vj7kcv+xESHPPhTzJ34ieMCL3pFg==

"@skalenetwork/skale-manager-interfaces@^3.2.0-develop.0":
version "3.2.0-paymaster.2"
Expand Down
Loading