From 4b7902ea13b827bea23667fc0d17bef63a9e40f3 Mon Sep 17 00:00:00 2001 From: Aahna Ashina <95955389+aahna-ashina@users.noreply.github.com> Date: Thu, 5 Oct 2023 19:06:52 +0700 Subject: [PATCH 1/9] feat: smart contract for checking passport status (#72) close #72 --- contracts/utils/IPassportUtils.sol | 18 ++++++++++++++++++ contracts/utils/PassportUtils.sol | 10 ++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 4 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 contracts/utils/IPassportUtils.sol create mode 100644 contracts/utils/PassportUtils.sol diff --git a/contracts/utils/IPassportUtils.sol b/contracts/utils/IPassportUtils.sol new file mode 100644 index 0000000..69e66df --- /dev/null +++ b/contracts/utils/IPassportUtils.sol @@ -0,0 +1,18 @@ +//SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.17; + +interface IPassportUtils { + /** + * Returns `true` if a citizen's passport has become revocable. + * + * @param passportID The NFT passport ID + */ + function isExpired(uint16 passportID) external view returns (bool); + + // /** + // * Returns the Unix epoch time when the passport will become revocable. + // * + // * @param passportID The NFT passport ID + // */ + // function getExpirationTimestamp(uint16 passportID) external view returns (uint256); +} diff --git a/contracts/utils/PassportUtils.sol b/contracts/utils/PassportUtils.sol new file mode 100644 index 0000000..ec91d71 --- /dev/null +++ b/contracts/utils/PassportUtils.sol @@ -0,0 +1,10 @@ +//SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.17; + +import "./IPassportUtils.sol"; + +contract PassportUtils is IPassportUtils { + function isExpired(uint16 passportID) public view returns (bool) { + return true; + } +} diff --git a/package-lock.json b/package-lock.json index edc2609..184ede6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "nationcred-contracts", - "version": "1.0.0", + "version": "0.5.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "nationcred-contracts", - "version": "1.0.0", + "version": "0.5.0", "license": "GPL-3.0-or-later", "dependencies": { "@openzeppelin/contracts": "^4.9.3" diff --git a/package.json b/package.json index 13be4be..3b66f70 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nationcred-contracts", - "version": "1.0.0", + "version": "0.5.0", "description": "NationCred smart contracts", "main": "index.js", "scripts": { From c970258970bf9d7463571134f5408de9d65d2959 Mon Sep 17 00:00:00 2001 From: Aahna Ashina <95955389+aahna-ashina@users.noreply.github.com> Date: Thu, 5 Oct 2023 20:10:25 +0700 Subject: [PATCH 2/9] npx prettier --- contracts/utils/IPassportUtils.sol | 24 ++++++++++++------------ contracts/utils/PassportUtils.sol | 6 +++--- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/contracts/utils/IPassportUtils.sol b/contracts/utils/IPassportUtils.sol index 69e66df..37d5213 100644 --- a/contracts/utils/IPassportUtils.sol +++ b/contracts/utils/IPassportUtils.sol @@ -2,17 +2,17 @@ pragma solidity ^0.8.17; interface IPassportUtils { - /** - * Returns `true` if a citizen's passport has become revocable. - * - * @param passportID The NFT passport ID - */ - function isExpired(uint16 passportID) external view returns (bool); + /** + * Returns `true` if a citizen's passport has become revocable. + * + * @param passportID The NFT passport ID + */ + function isExpired(uint16 passportID) external view returns (bool); - // /** - // * Returns the Unix epoch time when the passport will become revocable. - // * - // * @param passportID The NFT passport ID - // */ - // function getExpirationTimestamp(uint16 passportID) external view returns (uint256); + // /** + // * Returns the Unix epoch time when the passport will become revocable. + // * + // * @param passportID The NFT passport ID + // */ + // function getExpirationTimestamp(uint16 passportID) external view returns (uint256); } diff --git a/contracts/utils/PassportUtils.sol b/contracts/utils/PassportUtils.sol index ec91d71..e3662e9 100644 --- a/contracts/utils/PassportUtils.sol +++ b/contracts/utils/PassportUtils.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.17; import "./IPassportUtils.sol"; contract PassportUtils is IPassportUtils { - function isExpired(uint16 passportID) public view returns (bool) { - return true; - } + function isExpired(uint16 passportID) public view returns (bool) { + return true; + } } From eadf828f3892373892b2ec530f34070148b9fa86 Mon Sep 17 00:00:00 2001 From: Aahna Ashina <95955389+aahna-ashina@users.noreply.github.com> Date: Fri, 6 Oct 2023 20:28:48 +0700 Subject: [PATCH 3/9] feat: smart contract for checking passport status (#72) #72 --- contracts/governance/IVotingEscrow.sol | 15 ++++++ contracts/mock/PassportIssuerMock.sol | 10 ++++ contracts/mock/VotingEscrowMock.sol | 21 ++++++++ contracts/passport/IPassportIssuer.sol | 6 +++ contracts/utils/IPassportUtils.sol | 6 +-- contracts/utils/PassportUtils.sol | 21 +++++++- scripts/deploy-passport-utils.ts | 35 +++++++++++++ test/PassportUtils.ts | 72 ++++++++++++++++++++++++++ 8 files changed, 181 insertions(+), 5 deletions(-) create mode 100644 contracts/governance/IVotingEscrow.sol create mode 100644 contracts/mock/PassportIssuerMock.sol create mode 100644 contracts/mock/VotingEscrowMock.sol create mode 100644 contracts/passport/IPassportIssuer.sol create mode 100644 scripts/deploy-passport-utils.ts create mode 100644 test/PassportUtils.ts diff --git a/contracts/governance/IVotingEscrow.sol b/contracts/governance/IVotingEscrow.sol new file mode 100644 index 0000000..b52aba6 --- /dev/null +++ b/contracts/governance/IVotingEscrow.sol @@ -0,0 +1,15 @@ +//SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.17; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +interface IVotingEscrow is IERC20 { + struct LockedBalance { + int128 amount; + uint256 end; + } + + function locked(address) external view returns (LockedBalance memory); + + // function balanceOf(address) external view returns (uint256); +} diff --git a/contracts/mock/PassportIssuerMock.sol b/contracts/mock/PassportIssuerMock.sol new file mode 100644 index 0000000..ec4e621 --- /dev/null +++ b/contracts/mock/PassportIssuerMock.sol @@ -0,0 +1,10 @@ +//SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.17; + +import "../passport/IPassportIssuer.sol"; + +contract PassportIssuerMock is IPassportIssuer { + function revokeUnderBalance() public view returns (uint256) { + return 1.5 * 1e18; + } +} diff --git a/contracts/mock/VotingEscrowMock.sol b/contracts/mock/VotingEscrowMock.sol new file mode 100644 index 0000000..7a408c2 --- /dev/null +++ b/contracts/mock/VotingEscrowMock.sol @@ -0,0 +1,21 @@ +//SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.17; + +import "../governance/IVotingEscrow.sol"; +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract VotingEscrowMock is ERC20, IVotingEscrow { + constructor() ERC20("Vote-escrowed NATION", "veNATION") { + _mint(msg.sender, 100 * 1e18); + } + + function locked( + address + ) public view returns (LockedBalance memory lockedBalance) { + LockedBalance memory lockedBalance = LockedBalance({ + amount: 1, + end: block.timestamp + }); + return lockedBalance; + } +} diff --git a/contracts/passport/IPassportIssuer.sol b/contracts/passport/IPassportIssuer.sol new file mode 100644 index 0000000..bd23efe --- /dev/null +++ b/contracts/passport/IPassportIssuer.sol @@ -0,0 +1,6 @@ +//SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.17; + +interface IPassportIssuer { + function revokeUnderBalance() external view returns (uint256); +} diff --git a/contracts/utils/IPassportUtils.sol b/contracts/utils/IPassportUtils.sol index 37d5213..7aa3fd9 100644 --- a/contracts/utils/IPassportUtils.sol +++ b/contracts/utils/IPassportUtils.sol @@ -5,14 +5,14 @@ interface IPassportUtils { /** * Returns `true` if a citizen's passport has become revocable. * - * @param passportID The NFT passport ID + * @param citizen The address of an NFT passport's owner */ - function isExpired(uint16 passportID) external view returns (bool); + function isExpired(address citizen) external view returns (bool); // /** // * Returns the Unix epoch time when the passport will become revocable. // * // * @param passportID The NFT passport ID // */ - // function getExpirationTimestamp(uint16 passportID) external view returns (uint256); + // function getExpirationTime(uint16 passportID) external view returns (uint256); } diff --git a/contracts/utils/PassportUtils.sol b/contracts/utils/PassportUtils.sol index e3662e9..746dc0d 100644 --- a/contracts/utils/PassportUtils.sol +++ b/contracts/utils/PassportUtils.sol @@ -2,9 +2,26 @@ pragma solidity ^0.8.17; import "./IPassportUtils.sol"; +import "../passport/IPassportIssuer.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import "hardhat/console.sol"; contract PassportUtils is IPassportUtils { - function isExpired(uint16 passportID) public view returns (bool) { - return true; + using SafeERC20 for IERC20; + + IPassportIssuer public passportIssuer; + IERC20 public votingEscrow; + + constructor(address passportIssuerAddress, address votingEscrowAddress) { + passportIssuer = IPassportIssuer(passportIssuerAddress); + votingEscrow = IERC20(votingEscrowAddress); + } + + function isExpired(address citizen) public view returns (bool) { + uint256 revokeUnderBalance = passportIssuer.revokeUnderBalance(); + console.log("revokeUnderBalance:", revokeUnderBalance); + uint256 votingEscrowBalance = votingEscrow.balanceOf(citizen); + console.log("votingEscrowBalance:", votingEscrowBalance); + return votingEscrowBalance < revokeUnderBalance; } } diff --git a/scripts/deploy-passport-utils.ts b/scripts/deploy-passport-utils.ts new file mode 100644 index 0000000..9399d88 --- /dev/null +++ b/scripts/deploy-passport-utils.ts @@ -0,0 +1,35 @@ +// We require the Hardhat Runtime Environment explicitly here. This is optional +// but useful for running the script in a standalone fashion through `node