refactor: use custom errors in solidity (#127)

* refactor: change ap reverts to custom error

* test: fix tests for custom errors

* refactor: change setApprovalForAccessPoint string reverts to custom error
This commit is contained in:
Felipe Mendes 2023-02-27 12:42:41 -03:00 committed by GitHub
parent b957e87a83
commit 969cd12d92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 59 additions and 56 deletions

View File

@ -10,7 +10,6 @@ error MustHaveAtLeastOneOwner();
error RoleAlreadySet();
contract FleekAccessControl is Initializable {
/**
* @dev All available collection roles.
*/
@ -127,8 +126,7 @@ contract FleekAccessControl is Initializable {
*/
function _revokeCollectionRole(CollectionRoles role, address account) internal {
if (!hasCollectionRole(role, account)) revert RoleAlreadySet();
if (role == CollectionRoles.Owner && _collectionRolesCounter[role] == 1)
revert MustHaveAtLeastOneOwner();
if (role == CollectionRoles.Owner && _collectionRolesCounter[role] == 1) revert MustHaveAtLeastOneOwner();
_collectionRoles[role][account] = false;
_collectionRolesCounter[role] -= 1;

View File

@ -9,8 +9,14 @@ import "./FleekAccessControl.sol";
import "./util/FleekStrings.sol";
import "./FleekPausable.sol";
error AccessPointNotExistent();
error AccessPointAlreadyExists();
error AccessPointScoreCannotBeLower();
error MustBeAccessPointOwner();
error MustBeTokenOwner(uint256 tokenId);
error ThereIsNoTokenMinted();
error InvalidTokenIdForAccessPoint();
error AccessPointCreationStatusAlreadySet();
contract FleekERC721 is Initializable, ERC721Upgradeable, FleekAccessControl, FleekPausable {
using Strings for uint256;
@ -40,11 +46,7 @@ contract FleekERC721 is Initializable, ERC721Upgradeable, FleekAccessControl, Fl
event NewAccessPoint(string apName, uint256 indexed tokenId, address indexed owner);
event RemoveAccessPoint(string apName, uint256 indexed tokenId, address indexed owner);
event ChangeAccessPointAutoApproval(
uint256 indexed token,
bool indexed settings,
address indexed triggeredBy
);
event ChangeAccessPointAutoApproval(uint256 indexed token, bool indexed settings, address indexed triggeredBy);
event ChangeAccessPointScore(string apName, uint256 indexed tokenId, uint256 score, address indexed triggeredBy);
@ -132,7 +134,7 @@ contract FleekERC721 is Initializable, ERC721Upgradeable, FleekAccessControl, Fl
* @dev Checks if the AccessPoint exists.
*/
modifier requireAP(string memory apName) {
require(_accessPoints[apName].owner != address(0), "FleekERC721: invalid AP");
if (_accessPoints[apName].owner == address(0)) revert AccessPointNotExistent();
_;
}
@ -161,7 +163,7 @@ contract FleekERC721 is Initializable, ERC721Upgradeable, FleekAccessControl, Fl
) public payable requireCollectionRole(CollectionRoles.Owner) returns (uint256) {
uint256 tokenId = _appIds;
_mint(to, tokenId);
_appIds += 1;
App storage app = _apps[tokenId];
@ -453,7 +455,7 @@ contract FleekERC721 is Initializable, ERC721Upgradeable, FleekAccessControl, Fl
function addAccessPoint(uint256 tokenId, string memory apName) public payable whenNotPaused {
// require(msg.value == 0.1 ether, "You need to pay at least 0.1 ETH"); // TODO: define a minimum price
_requireMinted(tokenId);
require(_accessPoints[apName].owner == address(0), "FleekERC721: AP already exists");
if (_accessPoints[apName].owner != address(0)) revert AccessPointAlreadyExists();
emit NewAccessPoint(apName, tokenId, msg.sender);
@ -494,14 +496,8 @@ contract FleekERC721 is Initializable, ERC721Upgradeable, FleekAccessControl, Fl
bool approved
) public requireTokenOwner(tokenId) {
AccessPoint storage accessPoint = _accessPoints[apName];
require(
accessPoint.tokenId == tokenId,
"FleekERC721: the passed tokenId is not the same as the access point's tokenId."
);
require(
accessPoint.status == AccessPointCreationStatus.DRAFT,
"FleekERC721: the access point creation status has been set before."
);
if (accessPoint.tokenId != tokenId) revert InvalidTokenIdForAccessPoint();
if (accessPoint.status != AccessPointCreationStatus.DRAFT) revert AccessPointCreationStatusAlreadySet();
if (approved) {
// Approval
@ -528,7 +524,7 @@ contract FleekERC721 is Initializable, ERC721Upgradeable, FleekAccessControl, Fl
*
*/
function removeAccessPoint(string memory apName) public whenNotPaused requireAP(apName) {
require(msg.sender == _accessPoints[apName].owner, "FleekERC721: must be AP owner");
if (msg.sender != _accessPoints[apName].owner) revert MustBeAccessPointOwner();
_accessPoints[apName].status = AccessPointCreationStatus.REMOVED;
uint256 tokenId = _accessPoints[apName].tokenId;
emit ChangeAccessPointStatus(apName, tokenId, AccessPointCreationStatus.REMOVED, msg.sender);
@ -587,7 +583,7 @@ contract FleekERC721 is Initializable, ERC721Upgradeable, FleekAccessControl, Fl
*
*/
function decreaseAccessPointScore(string memory apName) public requireAP(apName) {
require(_accessPoints[apName].score > 0, "FleekERC721: score cant be lower");
if (_accessPoints[apName].score == 0) revert AccessPointScoreCannotBeLower();
_accessPoints[apName].score--;
emit ChangeAccessPointScore(apName, _accessPoints[apName].tokenId, _accessPoints[apName].score, msg.sender);
}

View File

@ -6,7 +6,7 @@ import "../TestBase.sol";
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
import {FleekAccessControl} from "contracts/FleekAccessControl.sol";
import "../../../../contracts/FleekERC721.sol";
import './ApBase.sol';
import "./ApBase.sol";
contract Test_FleekERC721_AccessPoint is Test_FleekERC721_Base, APConstants {
using Strings for address;
@ -37,7 +37,7 @@ contract Test_FleekERC721_AccessPoint is Test_FleekERC721_Base, APConstants {
string memory accessPointName = "accesspoint.com";
CuT.addAccessPoint(tokenId, accessPointName);
CuT.removeAccessPoint(accessPointName);
APConstants.assertAccessPointJSON(
accessPointName,
"0",

View File

@ -20,19 +20,19 @@ abstract contract Test_FleekERC721_Assertions is Test {
}
function expectRevertWithAPAlreadyExists() public {
vm.expectRevert("FleekERC721: AP already exists");
vm.expectRevert(AccessPointAlreadyExists.selector);
}
function expectRevertWithMustBeAPOwner() public {
vm.expectRevert("FleekERC721: must be AP owner");
vm.expectRevert(MustBeAccessPointOwner.selector);
}
function expectRevertWithInvalidAP() public {
vm.expectRevert("FleekERC721: invalid AP");
vm.expectRevert(AccessPointNotExistent.selector);
}
function expectRevertWithMinimalScore() public {
vm.expectRevert("FleekERC721: score cant be lower");
vm.expectRevert(AccessPointScoreCannotBeLower.selector);
}
function expectRevertWithInvalidTokenId() public {

View File

@ -1,7 +1,6 @@
import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
import { expect } from 'chai';
import { before } from 'mocha';
import { TestConstants, Fixtures } from '../helpers';
import { TestConstants, Fixtures, Errors } from '../helpers';
const { AccessPointStatus } = TestConstants;
describe('FleekERC721.AccessPoints.AutoApprovalOff', () => {
@ -54,7 +53,7 @@ describe('FleekERC721.AccessPoints.AutoApprovalOff', () => {
await expect(
contract.getAccessPointJSON('accesspoint.com')
).to.be.revertedWith('FleekERC721: invalid AP');
).to.be.revertedWithCustomError(contract, Errors.AccessPointNotExistent);
});
it('should increase the AP score', async () => {
@ -126,7 +125,7 @@ describe('FleekERC721.AccessPoints.AutoApprovalOff', () => {
await expect(
contract.connect(otherAccount).removeAccessPoint('accesspoint.com')
).to.be.revertedWith('FleekERC721: must be AP owner');
).to.be.revertedWithCustomError(contract, Errors.MustBeAccessPointOwner);
});
it('should not be allowed to add the same AP more than once', async () => {
@ -136,7 +135,7 @@ describe('FleekERC721.AccessPoints.AutoApprovalOff', () => {
await expect(
contract.addAccessPoint(tokenId, 'accesspoint.com')
).to.be.revertedWith('FleekERC721: AP already exists');
).to.be.revertedWithCustomError(contract, Errors.AccessPointAlreadyExists);
});
it('should change "contentVerified" to true', async () => {
@ -204,10 +203,7 @@ describe('FleekERC721.AccessPoints.AutoApprovalOff', () => {
it('should token owner be able to change the auto approval settings to on', async () => {
const { contract, tokenId, owner } = fixture;
await contract
.connect(owner)
.setAccessPointAutoApproval(tokenId, true);
await contract.connect(owner).setAccessPointAutoApproval(tokenId, true);
await contract.addAccessPoint(tokenId, 'accesspoint.com');

View File

@ -1,7 +1,6 @@
import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
import { expect } from 'chai';
import { before } from 'mocha';
import { TestConstants, Fixtures } from '../helpers';
import { TestConstants, Fixtures, Errors } from '../helpers';
const { AccessPointStatus } = TestConstants;
describe('FleekERC721.AccessPoints.AutoApprovalOn', () => {
@ -45,9 +44,9 @@ describe('FleekERC721.AccessPoints.AutoApprovalOn', () => {
it('should revert if AP does not exist', async () => {
const { contract, tokenId } = fixture;
await expect(contract.getAccessPointJSON('random.com')).to.be.revertedWith(
'FleekERC721: invalid AP'
);
await expect(
contract.getAccessPointJSON('random.com')
).to.be.revertedWithCustomError(contract, Errors.AccessPointNotExistent);
});
it('should increase the AP score', async () => {
@ -120,7 +119,7 @@ describe('FleekERC721.AccessPoints.AutoApprovalOn', () => {
await expect(
contract.connect(otherAccount).removeAccessPoint(DefaultAP)
).to.be.revertedWith('FleekERC721: must be AP owner');
).to.be.revertedWithCustomError(contract, Errors.MustBeAccessPointOwner);
});
it('should not be allowed to add the same AP more than once', async () => {
@ -128,7 +127,7 @@ describe('FleekERC721.AccessPoints.AutoApprovalOn', () => {
await expect(
contract.addAccessPoint(tokenId, DefaultAP)
).to.be.revertedWith('FleekERC721: AP already exists');
).to.be.revertedWithCustomError(contract, Errors.AccessPointAlreadyExists);
});
it('should change "contentVerified" to true', async () => {

View File

@ -1,4 +1,8 @@
export const Errors = Object.freeze({
AccessPointNotExistent: 'AccessPointNotExistent',
AccessPointAlreadyExists: 'AccessPointAlreadyExists',
AccessPointScoreCannotBeLower: 'AccessPointScoreCannotBeLower',
MustBeAccessPointOwner: 'MustBeAccessPointOwner',
MustHaveCollectionRole: 'MustHaveCollectionRole',
MustHaveTokenRole: 'MustHaveTokenRole',
MustHaveAtLeastOneOwner: 'MustHaveAtLeastOneOwner',

View File

@ -159,8 +159,7 @@ export function handleNewMint(event: NewMintEvent): void {
let commitHash = event.params.commitHash;
let logo = event.params.logo;
let color = event.params.color;
let accessPointAutoApproval =
event.params.accessPointAutoApproval;
let accessPointAutoApproval = event.params.accessPointAutoApproval;
let tokenId = event.params.tokenId;
let ownerAddress = event.params.owner;
@ -173,8 +172,7 @@ export function handleNewMint(event: NewMintEvent): void {
newMintEntity.gitRepository = gitRepository;
newMintEntity.logo = logo;
newMintEntity.color = color;
newMintEntity.accessPointAutoApproval =
accessPointAutoApproval;
newMintEntity.accessPointAutoApproval = accessPointAutoApproval;
newMintEntity.triggeredBy = event.params.minter;
newMintEntity.tokenOwner = ownerAddress;
newMintEntity.blockNumber = event.block.number;
@ -229,8 +227,10 @@ export function handleNewMint(event: NewMintEvent): void {
token.save();
}
export function handleMetadataUpdateWithStringValue(event: MetadataUpdateEvent): void {
/**
export function handleMetadataUpdateWithStringValue(
event: MetadataUpdateEvent
): void {
/**
* Metadata handled here:
* setTokenExternalURL
* setTokenENS
@ -252,7 +252,9 @@ export function handleMetadataUpdateWithStringValue(event: MetadataUpdateEvent):
entity.save();
// UPDATE TOKEN
let token = Token.load(Bytes.fromByteArray(Bytes.fromBigInt(event.params._tokenId)));
let token = Token.load(
Bytes.fromByteArray(Bytes.fromBigInt(event.params._tokenId))
);
if (token) {
if (event.params.key == 'externalURL') {
@ -266,12 +268,14 @@ export function handleMetadataUpdateWithStringValue(event: MetadataUpdateEvent):
} else {
// logo
token.logo = event.params.value;
}
}
token.save();
}
}
export function handleMetadataUpdateWithDoubleStringValue(event: MetadataUpdateEvent2): void {
export function handleMetadataUpdateWithDoubleStringValue(
event: MetadataUpdateEvent2
): void {
/**
* setTokenBuild
*/
@ -289,7 +293,9 @@ export function handleMetadataUpdateWithDoubleStringValue(event: MetadataUpdateE
entity.save();
// UPDATE TOKEN
let token = Token.load(Bytes.fromByteArray(Bytes.fromBigInt(event.params._tokenId)));
let token = Token.load(
Bytes.fromByteArray(Bytes.fromBigInt(event.params._tokenId))
);
if (token) {
if (event.params.key == 'build') {
@ -302,11 +308,13 @@ export function handleMetadataUpdateWithDoubleStringValue(event: MetadataUpdateE
token.gitRepository = event.params.value[1];
token.save();
gitRepositoryEntity.save();
}
}
}
}
export function handleMetadataUpdateWithIntValue(event: MetadataUpdateEvent1): void {
export function handleMetadataUpdateWithIntValue(
event: MetadataUpdateEvent1
): void {
/**
* setTokenColor
*/
@ -323,7 +331,9 @@ export function handleMetadataUpdateWithIntValue(event: MetadataUpdateEvent1): v
entity.save();
let token = Token.load(Bytes.fromByteArray(Bytes.fromBigInt(event.params._tokenId)));
let token = Token.load(
Bytes.fromByteArray(Bytes.fromBigInt(event.params._tokenId))
);
if (token) {
if (event.params.key == 'color') {