Skip to content

Commit

Permalink
feat: add unit test & fix bugs (#220)
Browse files Browse the repository at this point in the history
* fix: fix ERC5727Example code size

* fix: remove package_lock.json

* feat: add core contract test

* feat: add ERC5727Delegate test

* feat: test Expirable & Claimable

* fix: onlyManger Expirable

* fix: fix vairable name

* fix: fix typo; format test title; fix merkle node inputs

* feat: add test ERC5727Enumerable

* feat: update ERC5727Governance test

* feat: update test

* feat: update test

* fix: fix ERC5727Recovery

* feat: add query methods; prevent duplicated sbt

* chore(release): 0.2.1-alpha.1

* fix: set organization

* feat: add support interface test

* fix: fix ERC5727Recovery and ERC721Enumerable bug

* feat: update test

* feat: update test

* fix: fix _beforeValueTransfer

* feat: remove access control

* fix: fix erc3525 spendAllowance

* feat: update test

* fix: update lockfile

* fix: fix lockfile

* fix: update lockfile

* fix: update lockfile

---------

Co-authored-by: Austin Zhu <austinzhu666@gmail.com>
  • Loading branch information
beyond009 and AustinZhu authored Apr 11, 2023
1 parent f957c3c commit 85ed7af
Show file tree
Hide file tree
Showing 32 changed files with 5,534 additions and 6,445 deletions.
27 changes: 24 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,34 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [0.2.0-alpha.1](https://github.com/desoul-labs/soulhub-contracts/compare/v0.1.0-alpha.1...v0.2.0-alpha.1) (2023-03-27)
### [0.2.1-alpha.1](https://github.com/desoul-labs/soulhub-contracts/compare/v0.2.0-alpha.1...v0.2.1-alpha.1) (2023-03-29)

### Features

- add core contract test ([fdfc056](https://github.com/desoul-labs/soulhub-contracts/commit/fdfc05639b29480c748be3416ec82f4f82ae65b2))
- add ERC5727Delegate test ([f46b4cd](https://github.com/desoul-labs/soulhub-contracts/commit/f46b4cd1b45a291dae29f00033c8af77beb248da))
- add query methods; prevent duplicated sbt ([e44eec0](https://github.com/desoul-labs/soulhub-contracts/commit/e44eec08314b4a0ae90164cd1a5de1750b847051))
- add test ERC5727Enumerable ([fea04bd](https://github.com/desoul-labs/soulhub-contracts/commit/fea04bd0e2fde79a97a8db90591a6f853f948d54))
- test Expirable & Claimable ([3d9b71f](https://github.com/desoul-labs/soulhub-contracts/commit/3d9b71fe6a591859204fb6bc409b8a99cf22d2e6))
- update ERC5727Governance test ([5e8fbdb](https://github.com/desoul-labs/soulhub-contracts/commit/5e8fbdba56ca39585f4d60758d861d41f7e35794))
- update test ([6c2cd5b](https://github.com/desoul-labs/soulhub-contracts/commit/6c2cd5bc4827104a478279cf1d22ecd766345cbf))
- update test ([79a7093](https://github.com/desoul-labs/soulhub-contracts/commit/79a70932d676c2a6f4053f31d5aea1d337248c2c))

### Bug Fixes

- fix ERC5727Example code size ([8348d65](https://github.com/desoul-labs/soulhub-contracts/commit/8348d65c3fe87db316b8ce479530b0d70ba3505d))
- fix ERC5727Recovery ([35b6809](https://github.com/desoul-labs/soulhub-contracts/commit/35b68090adb290a9e3f79fa7ab00b3119246c22b))
- fix typo; format test title; fix merkle node inputs ([9b64c0f](https://github.com/desoul-labs/soulhub-contracts/commit/9b64c0fa27dd8e90da6f8f2ca84e6f7f58e98be3))
- fix vairable name ([b1c6a8e](https://github.com/desoul-labs/soulhub-contracts/commit/b1c6a8e82c52e17fb20c5146165f5333f2ac088d))
- onlyManger Expirable ([76f9468](https://github.com/desoul-labs/soulhub-contracts/commit/76f9468ee558b13928ac6040a76c0e237ffc2381))
- remove package_lock.json ([fb48654](https://github.com/desoul-labs/soulhub-contracts/commit/fb4865459240baf5448d068055cdeb4bcb20bace))

## [0.2.0-alpha.1](https://github.com/desoul-labs/soulhub-contracts/compare/v0.1.0-alpha.1...v0.2.0-alpha.1) (2023-03-27)

### Bug Fixes

* remove unused storage variables ([162fd11](https://github.com/desoul-labs/soulhub-contracts/commit/162fd11b84e2ccb39cdef52ac20a4c70290e8fc4))
* slot is not initlized ([2267b4c](https://github.com/desoul-labs/soulhub-contracts/commit/2267b4c7992e79167c6b081c550529b407857efa))
- remove unused storage variables ([162fd11](https://github.com/desoul-labs/soulhub-contracts/commit/162fd11b84e2ccb39cdef52ac20a4c70290e8fc4))
- slot is not initlized ([2267b4c](https://github.com/desoul-labs/soulhub-contracts/commit/2267b4c7992e79167c6b081c550529b407857efa))

## [0.1.0-alpha.1](https://github.com/desoul-labs/soulhub-contracts/compare/v0.0.3...v0.1.0-alpha.1) (2023-03-08)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ abstract contract ERC3525SlotEnumerableUpgradeable is

mapping(uint256 => EnumerableSetUpgradeable.UintSet) private _tokensInSlot;

EnumerableSetUpgradeable.UintSet private _allSlots;
EnumerableSetUpgradeable.UintSet internal _allSlots;

function __ERC3525SlotEnumerable_init() internal onlyInitializing {
__ERC3525SlotEnumerable_init_unchained();
Expand Down
1 change: 1 addition & 0 deletions contracts-upgradeable/ERC3525/ERC3525Upgradeable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ contract ERC3525Upgradeable is
uint256 tokenId,
uint256 value
) internal virtual {
if (ownerOf(tokenId) == operator) return;
uint256 currentAllowance = ERC3525Upgradeable.allowance(
tokenId,
operator
Expand Down
19 changes: 17 additions & 2 deletions contracts-upgradeable/ERC5727/ERC5727ClaimableUpgradeable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,31 @@ abstract contract ERC5727ClaimableUpgradeable is
if (_claimed[to].contains(slot)) revert AlreadyClaimed();

bytes32 node = keccak256(
abi.encodePacked(to, tokenId, amount, slot, burnAuth, data)
abi.encodePacked(
to,
tokenId,
amount,
slot,
burnAuth,
verifier,
data
)
);
if (!proof.verify(merkelRoot, node)) revert Unauthorized(to);
if (!proof.verifyCalldata(merkelRoot, node)) revert Unauthorized(to);

_issue(_slotIssuers[slot], to, tokenId, slot, burnAuth, verifier);
_issue(_slotIssuers[slot], tokenId, amount);

_claimed[to].add(slot);
}

function isClaimed(
address to,
uint256 slot
) public view virtual returns (bool) {
return _claimed[to].contains(slot);
}

function supportsInterface(
bytes4 interfaceId
)
Expand Down
10 changes: 5 additions & 5 deletions contracts-upgradeable/ERC5727/ERC5727DelegateUpgradeable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ abstract contract ERC5727DelegateUpgradeable is
) external virtual override onlyAdmin {
if (operator == address(0) || slot == 0) revert NullValue();
if (isOperatorFor(operator, slot))
revert RoleAlreadyGranted(operator, MINTER_ROLE ^ bytes32(slot));
revert RoleAlreadyGranted(operator, "voter");

_grantRole(MINTER_ROLE ^ bytes32(slot), operator);
_minterRole[slot][operator] = true;
emit Delegate(operator, slot);
}

Expand All @@ -32,9 +32,9 @@ abstract contract ERC5727DelegateUpgradeable is
) external virtual override onlyAdmin {
if (operator == address(0) || slot == 0) revert NullValue();
if (!isOperatorFor(operator, slot))
revert RoleNotGranted(operator, MINTER_ROLE ^ bytes32(slot));
revert RoleNotGranted(operator, "voter");

_revokeRole(MINTER_ROLE ^ bytes32(slot), operator);
_minterRole[slot][operator] = false;
emit UnDelegate(operator, slot);
}

Expand All @@ -44,7 +44,7 @@ abstract contract ERC5727DelegateUpgradeable is
) public view virtual override returns (bool) {
if (operator == address(0) || slot == 0) revert NullValue();

return hasRole(MINTER_ROLE ^ bytes32(slot), operator);
return _minterRole[slot][operator];
}

function supportsInterface(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ abstract contract ERC5727EnumerableUpgradeable is
function ownerBalanceInSlot(
address owner,
uint256 slot
) external view returns (uint256) {
) public view returns (uint256) {
if (owner == address(0)) revert NullValue();
if (!_slotExists(slot)) revert NotFound(slot);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ abstract contract ERC5727ExpirableUpgradeable is

modifier onlyManager(uint256 tokenId) {
if (
_msgSender() != _issuers[tokenId] ||
_msgSender() != _issuers[tokenId] &&
_msgSender() != ownerOf(tokenId)
) revert Unauthorized(_msgSender());
_;
Expand Down
24 changes: 16 additions & 8 deletions contracts-upgradeable/ERC5727/ERC5727GovernanceUpgradeable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ abstract contract ERC5727GovernanceUpgradeable is
address verifier;
}

bytes32 public constant VOTER_ROLE = bytes32(uint256(0x04));
mapping(address => bool) internal _voterRole;

EnumerableSetUpgradeable.AddressSet private _voters;

Expand All @@ -55,7 +55,7 @@ abstract contract ERC5727GovernanceUpgradeable is
address admin_
) internal onlyInitializing {
_voters.add(admin_);
_setupRole(VOTER_ROLE, admin_);
_voterRole[admin_] = true;
}

function requestApproval(
Expand Down Expand Up @@ -107,18 +107,17 @@ abstract contract ERC5727GovernanceUpgradeable is

function addVoter(address newVoter) public virtual onlyAdmin {
if (newVoter == address(0)) revert NullValue();
if (hasRole(VOTER_ROLE, newVoter))
revert RoleAlreadyGranted(newVoter, VOTER_ROLE);
if (_voterRole[newVoter]) revert RoleAlreadyGranted(newVoter, "voter");

_voters.add(newVoter);
_setupRole(VOTER_ROLE, newVoter);
_voterRole[newVoter] = true;
}

function removeVoter(address voter) public virtual onlyAdmin {
if (voter == address(0)) revert NullValue();
if (!_voters.contains(voter)) revert RoleNotGranted(voter, VOTER_ROLE);
if (!_voters.contains(voter)) revert RoleNotGranted(voter, "voter");

_revokeRole(VOTER_ROLE, voter);
_voterRole[voter] = false;
_voters.remove(voter);
}

Expand All @@ -133,7 +132,7 @@ abstract contract ERC5727GovernanceUpgradeable is
}

function isVoter(address voter) public view virtual returns (bool) {
return hasRole(VOTER_ROLE, voter);
return _voterRole[voter];
}

function voteApproval(
Expand Down Expand Up @@ -184,6 +183,15 @@ abstract contract ERC5727GovernanceUpgradeable is
data;
}

function getApproval(
uint256 approvalId
) public view virtual returns (IssueApproval memory) {
if (_approvals[approvalId].creator == address(0))
revert NotFound(approvalId);

return _approvals[approvalId];
}

function approvalURI(
uint256 approvalId
) public view virtual override returns (string memory) {
Expand Down
8 changes: 4 additions & 4 deletions contracts-upgradeable/ERC5727/ERC5727RecoveryUpgradeable.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

import "@openzeppelin/contracts-upgradeable/utils/cryptography/SignatureCheckerUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol";

import "./ERC5727EnumerableUpgradeable.sol";
import "./interfaces/IERC5727RecoveryUpgradeable.sol";
Expand All @@ -10,7 +10,7 @@ abstract contract ERC5727RecoveryUpgradeable is
IERC5727RecoveryUpgradeable,
ERC5727EnumerableUpgradeable
{
using SignatureCheckerUpgradeable for address;
using ECDSAUpgradeable for bytes32;

bytes32 private constant _RECOVERY_TYPEHASH =
keccak256("Recovery(address from,address recipient)");
Expand All @@ -30,9 +30,9 @@ abstract contract ERC5727RecoveryUpgradeable is
if (from == recipient) revert MethodNotAllowed(recipient);

bytes32 digest = _hashTypedDataV4(
keccak256(abi.encodePacked(_RECOVERY_TYPEHASH, from, recipient))
keccak256(abi.encode(_RECOVERY_TYPEHASH, from, recipient))
);
if (!from.isValidSignatureNow(digest, signature)) revert Forbidden();
if (digest.recover(signature) != from) revert Forbidden();

uint256 balance = balanceOf(from);
for (uint256 i = 0; i < balance; ) {
Expand Down
30 changes: 12 additions & 18 deletions contracts-upgradeable/ERC5727/ERC5727Upgradeable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/cryptography/SignatureCheckerUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

import "../ERC3525/ERC3525Upgradeable.sol";
import "../ERC5192/interfaces/IERC5192Upgradeable.sol";
Expand All @@ -18,7 +18,7 @@ import "./interfaces/IERC5727EnumerableUpgradeable.sol";

contract ERC5727Upgradeable is
EIP712Upgradeable,
AccessControlEnumerableUpgradeable,
OwnableUpgradeable,
ERC3525Upgradeable,
IERC5727MetadataUpgradeable
{
Expand All @@ -34,17 +34,16 @@ contract ERC5727Upgradeable is
mapping(uint256 => address) internal _slotVerifiers;
mapping(uint256 => BurnAuth) internal _slotBurnAuths;

bytes32 public constant MINTER_ROLE = bytes32(uint256(0x01));
bytes32 public constant BURNER_ROLE = bytes32(uint256(0x02));
mapping(uint256 => mapping(address => bool)) internal _minterRole;
mapping(uint256 => mapping(address => bool)) internal _burnerRole;

bytes32 private constant _TOKEN_TYPEHASH =
keccak256(
"Token(uint256 tokenId,address owner,uint256 value,uint256 slot,address issuer,address verifier,BurnAuth burnAuth)"
);

modifier onlyAdmin() {
if (!hasRole(DEFAULT_ADMIN_ROLE, _msgSender()))
revert Unauthorized(_msgSender());
if (owner() != _msgSender()) revert Unauthorized(_msgSender());
_;
}

Expand Down Expand Up @@ -81,7 +80,8 @@ contract ERC5727Upgradeable is
function __ERC5727_init_unchained(
address admin_
) internal onlyInitializing {
_setupRole(DEFAULT_ADMIN_ROLE, admin_);
__Ownable_init_unchained();
transferOwnership(admin_);
}

function verifierOf(
Expand Down Expand Up @@ -144,11 +144,11 @@ contract ERC5727Upgradeable is
_verifiers[tokenId] = verifier;

if (auth == BurnAuth.IssuerOnly || auth == BurnAuth.Both) {
_grantRole(BURNER_ROLE ^ bytes32(tokenId), from);
_burnerRole[tokenId][from] = true;
_approve(from, tokenId);
}
if (auth == BurnAuth.OwnerOnly || auth == BurnAuth.Both) {
_grantRole(BURNER_ROLE ^ bytes32(tokenId), to);
_burnerRole[tokenId][to] = true;
}

emit Issued(from, to, tokenId, auth);
Expand Down Expand Up @@ -215,16 +215,14 @@ contract ERC5727Upgradeable is
address from,
uint256 tokenId
) internal view virtual returns (bool) {
return hasRole(BURNER_ROLE ^ bytes32(tokenId), from);
return _burnerRole[tokenId][from];
}

function _checkMintAuth(
address from,
uint256 slot
) internal view virtual returns (bool) {
return
hasRole(DEFAULT_ADMIN_ROLE, from) ||
hasRole(MINTER_ROLE ^ bytes32(slot), from);
return (owner() == from) || _minterRole[slot][from];
}

function _burn(uint256 tokenId) internal virtual override {
Expand Down Expand Up @@ -328,11 +326,7 @@ contract ERC5727Upgradeable is
public
view
virtual
override(
IERC165Upgradeable,
ERC3525Upgradeable,
AccessControlEnumerableUpgradeable
)
override(IERC165Upgradeable, ERC3525Upgradeable)
returns (bool)
{
return
Expand Down
Loading

0 comments on commit 85ed7af

Please sign in to comment.