From 29811eb504a23301abac978b31ed029e4d2d182a Mon Sep 17 00:00:00 2001 From: thurendous Date: Fri, 13 Sep 2024 19:42:07 +0900 Subject: [PATCH] add some readme and some doc in code --- .gas-snapshot | 156 ++++++++++++++++++++++++++++ README.md | 2 + changelog.md | 38 ------- src/GovToken.sol | 17 ++- test/unit/GovToken.t.sol | 67 +++++++++++- test/unit/VotingPowerExchange.t.sol | 90 ++++++++++++++++ 6 files changed, 328 insertions(+), 42 deletions(-) create mode 100644 .gas-snapshot delete mode 100644 changelog.md diff --git a/.gas-snapshot b/.gas-snapshot new file mode 100644 index 0000000..abd7943 --- /dev/null +++ b/.gas-snapshot @@ -0,0 +1,156 @@ +AmbassadorTest:testBalanceOfBatchWorks() (gas: 26010) +AmbassadorTest:testBalanceOfWorks() (gas: 31180) +AmbassadorTest:testBurnBatchCanBeCalledByBurner() (gas: 75954) +AmbassadorTest:testBurnBatchWillFailByNonBurner() (gas: 85060) +AmbassadorTest:testBurningTokenSuccessfully() (gas: 115515) +AmbassadorTest:testBurningTokenWillFailByNonBurner() (gas: 127990) +AmbassadorTest:testBurningTokenWillSucceedByNewBurner() (gas: 140025) +AmbassadorTest:testConstructorWillRevertIfAdminIsZero() (gas: 49376) +AmbassadorTest:testMintBatchWillWork() (gas: 81972) +AmbassadorTest:testMintingTokenWillFailByNonMinter() (gas: 29783) +AmbassadorTest:testMintingTokenWillSucceedByNewMinter() (gas: 165748) +AmbassadorTest:testMintingTokensSuccessfully() (gas: 123301) +AmbassadorTest:testSetURI() (gas: 51205) +AmbassadorTest:testSetURIByNonUriSetter() (gas: 12128) +AmbassadorTest:testSupportsInterface() (gas: 16538) +AmbassadorTest:testTokenRoles() (gas: 39075) +AmbassadorTest:testTransferWillWork() (gas: 61413) +ERC20UpgradeableTokenV1Test:testApprovingAllAndTransferFromAll() (gas: 67881) +ERC20UpgradeableTokenV1Test:testApprovingAllAndTransferFromHalf() (gas: 90094) +ERC20UpgradeableTokenV1Test:testApprovingAndTransferFrom() (gas: 70217) +ERC20UpgradeableTokenV1Test:testApprovingSpending() (gas: 47204) +ERC20UpgradeableTokenV1Test:testDefaultAdminCannotBeZero() (gas: 3404094) +ERC20UpgradeableTokenV1Test:testFailingToBurnTokens() (gas: 35201) +ERC20UpgradeableTokenV1Test:testGrantRoles() (gas: 63145) +ERC20UpgradeableTokenV1Test:testGrantingAndRevokingRoles() (gas: 49891) +ERC20UpgradeableTokenV1Test:testPausingAndUnpausingSuccessfully() (gas: 36164) +ERC20UpgradeableTokenV1Test:testRolesAreSetCorrectly() (gas: 45900) +ERC20UpgradeableTokenV1Test:testSendingTokens() (gas: 89772) +ERC20UpgradeableTokenV1Test:testShowingBasicTokenInfo() (gas: 31607) +ERC20UpgradeableTokenV1Test:testSucceedingToBurnTokens() (gas: 39063) +ERC20UpgradeableTokenV1Test:testUpgradeabilityOfToken() (gas: 3680933) +ERC20UpgradeableTokenV1Test:testWhenPausedNoMintingOrTransferringIsAllowed() (gas: 61788) +GovTokenTest:testBurningCanBeDoneByBurner() (gas: 71425) +GovTokenTest:testBurningCanBeDoneByNewBurner() (gas: 104676) +GovTokenTest:testBurningCannotBeDoneByNonBurner() (gas: 31512) +GovTokenTest:testClock() (gas: 14358) +GovTokenTest:testClockMode() (gas: 11350) +GovTokenTest:testDelegateBySig() (gas: 90761) +GovTokenTest:testDelegates() (gas: 29514) +GovTokenTest:testGovTokenDefaultAdminCannotBeZero() (gas: 98903) +GovTokenTest:testInitialVotes() (gas: 28882) +GovTokenTest:testMintingCanBeDoneByMinter() (gas: 95606) +GovTokenTest:testMintingCanBeDoneByNewMinter() (gas: 126921) +GovTokenTest:testMintingCannotBeDoneByNonMinter() (gas: 41757) +GovTokenTest:testNonRoleCannotCallSetBurnedAmountOfUtilToken() (gas: 31075) +GovTokenTest:testNonces() (gas: 67641) +GovTokenTest:testSetBurnedAmountOfUtilTokenEvent() (gas: 77722) +GovTokenTest:testTheRolesOfTheGovToken() (gas: 31013) +GovTokenTest:testTheTokenInfos() (gas: 21406) +GovTokenTest:testTokensAreNotTransferrable() (gas: 49053) +GovTokenTest:testVotesAfterDelegateToOther() (gas: 141319) +GovTokenTest:testVotesAfterSelfDelegate() (gas: 100610) +GovTokenTest:testVotingPowerExchangeCanCallSetBurnedAmountOfUtilToken() (gas: 73352) +VotingPowerExchangeTest:testBasicVotingPowerExchangeInfo() (gas: 14590) +VotingPowerExchangeTest:testCalculateIncrementedBurningAmountWhenCurrentIsNotZero() (gas: 48619) +VotingPowerExchangeTest:testCalculateIncrementedBurningAmountWhenCurrentIsZero() (gas: 41986) +VotingPowerExchangeTest:testCalculationOfIncreasedVotingPowerWhenCurrentIsNotZero() (gas: 70426) +VotingPowerExchangeTest:testCalculationOfIncreasedVotingPowerWhenCurrentIsZero() (gas: 50901) +VotingPowerExchangeTest:testConstantValues() (gas: 11697) +VotingPowerExchangeTest:testConstructorOfVotingPowerExchange() (gas: 2236713) +VotingPowerExchangeTest:testExchangeFailCaseWhenAmountIsTooSmall() (gas: 41022) +VotingPowerExchangeTest:testExchangeFailCaseWhenNonceIsUsed() (gas: 202448) +VotingPowerExchangeTest:testExchangeFailCaseWhenSenderIsNotSigner() (gas: 67348) +VotingPowerExchangeTest:testExchangeFailCaseWhenSignatureExpired() (gas: 44099) +VotingPowerExchangeTest:testExchangeFailCaseWhenSignatureIsInvalid() (gas: 67050) +VotingPowerExchangeTest:testExchangeFailCaseWhenUserGotMoreThanVotingPowerCap() (gas: 133248) +VotingPowerExchangeTest:testExchangeFailsWhenSenderIsZeroAddress() (gas: 38841) +VotingPowerExchangeTest:testExchangeLargeAmountSuccessCase() (gas: 210242) +VotingPowerExchangeTest:testExchangeMediumAmountSuccessCase() (gas: 215165) +VotingPowerExchangeTest:testExchangeSmallAmountSuccessCase() (gas: 210504) +VotingPowerExchangeTest:testExchangeTwiceToCrossVotingPowerCapFailureCase() (gas: 249775) +VotingPowerExchangeTest:testExchangeTwiceToGetToVotingPowerCapSuccessCase() (gas: 304984) +VotingPowerExchangeTest:testExchangeVotingPowerCapSuccessCase() (gas: 221279) +VotingPowerExchangeTest:testGovTokenBasicInfo() (gas: 25278) +VotingPowerExchangeTest:testGovTokenNotBeingTransferrable() (gas: 68747) +VotingPowerExchangeTest:testReturnedSetupValues() (gas: 63204) +VotingPowerExchangeTest:testSettingVotingPowerCap() (gas: 25153) +VotingPowerExchangeTest:testSettingVotingPowerCapFails() (gas: 14249) +VotingPowerExchangeTest:testSettingVotingPowerCapFailsCase2() (gas: 23198) +VotingPowerExchangeTest:testTokensAccessRoles() (gas: 70485) +VotingPowerExchangeTest:testTokensBalanceOf() (gas: 27834) +VotingPowerExchangeTest:testTokensBurning() (gas: 86324) +VotingPowerExchangeTest:testUtilityTokenBasicInfo() (gas: 31675) +VotingPowerExchangeTest:testUtilityTokenCanBeTransferred() (gas: 88383) +VotingPowerExchangeTest:testUtilityTokensPausability() (gas: 76194) +VotingPowerExchangeTest:testVotingPowerCap() (gas: 11060) +VotingPowerExchangeTest:testVotingPowerExchangesRoles() (gas: 57604) +VotingPowerExchangeUnitTest:testCalculateBurningAmountFromVotingPower() (gas: 347974) +VotingPowerExchangeUnitTest:testCalculateIncrementedBurningAmount() (gas: 55875) +VotingPowerExchangeUnitTest:testCalculateIncrementedVotingPower() (gas: 77126) +VotingPowerExchangeUnitTest:testCalculateVotingPowerFromBurnedAmount() (gas: 480905) +VotingPowerExchangeUnitTest:testCalculateVotingPowerFromBurnedAmountRareCases() (gas: 34497) +VotingPowerExchangeUnitTest:testCalculationOfVotingPowerMintingWhenMintedSeparately() (gas: 17907) +VotingPowerExchangeUnitTest:testCalculationOfVotingPowerMintingWhenMintedSeparately2() (gas: 18027) +VotingPowerExchangeUnitTest:testConstructorValidation() (gas: 109717) +VotingPowerExchangeUnitTest:testSomeMoreSpecialCasesForCalculateVotingPowerFromBurnedAmount() (gas: 15833) +VotingPowerExchangeUnitTest:testSpecialCasesForCalculateVotingPowerFromBurnedAmount() (gas: 15772) +VotingPwoerExchangeTest:testCalculateIncrementedVotingPower(uint256) (runs: 4104, μ: 20724, ~: 20079) +VotingPwoerExchangeTest:testCalculateIncrementedVotingPower_0_to_10(uint256) (runs: 4104, μ: 20700, ~: 20033) +VotingPwoerExchangeTest:testCalculateIncrementedVotingPower_100_to_110(uint256) (runs: 4104, μ: 20643, ~: 19997) +VotingPwoerExchangeTest:testCalculateIncrementedVotingPower_10_to_110(uint256) (runs: 4104, μ: 21431, ~: 21491) +VotingPwoerExchangeTest:testCalculateIncrementedVotingPower_10_to_20(uint256) (runs: 4104, μ: 20715, ~: 20060) +VotingPwoerExchangeTest:testCalculateIncrementedVotingPower_20_to_30(uint256) (runs: 4104, μ: 20735, ~: 20082) +VotingPwoerExchangeTest:testCalculateIncrementedVotingPower_30_to_40(uint256) (runs: 4104, μ: 20829, ~: 20178) +VotingPwoerExchangeTest:testCalculateIncrementedVotingPower_40_to_50(uint256) (runs: 4104, μ: 20768, ~: 20122) +VotingPwoerExchangeTest:testCalculateIncrementedVotingPower_50_to_60(uint256) (runs: 4104, μ: 20889, ~: 20238) +VotingPwoerExchangeTest:testCalculateIncrementedVotingPower_60_to_70(uint256) (runs: 4104, μ: 20852, ~: 20215) +VotingPwoerExchangeTest:testCalculateIncrementedVotingPower_70_to_80(uint256) (runs: 4104, μ: 20713, ~: 20065) +VotingPwoerExchangeTest:testCalculateIncrementedVotingPower_80_to_90(uint256) (runs: 4104, μ: 20663, ~: 20021) +VotingPwoerExchangeTest:testCalculateIncrementedVotingPower_90_to_100(uint256) (runs: 4104, μ: 20665, ~: 20024) +VotingPwoerExchangeTest:testExchangeWithAnyAmountLessThan1e18WillRevert(uint256) (runs: 4100, μ: 41692, ~: 41692) +VotingPwoerExchangeTest:testExchangeWithAnyAmountWhichIsInRangeWillSucceed(uint256) (runs: 4104, μ: 218340, ~: 218466) +VotingPwoerExchangeTest:testExchangeWithAnyAmountWithinNewCapWillSucceed(uint256) (runs: 4104, μ: 229223, ~: 229377) +VotingPwoerExchangeTest:testExchangeWithAnyExpirationWhichIsExpiredWillRevert(uint256) (runs: 4104, μ: 46557, ~: 47250) +VotingPwoerExchangeTest:testExchangeWithAnyExpirationWhichIsNotExpiredWillSucceed(uint256) (runs: 4103, μ: 228136, ~: 228136) +VotingPwoerExchangeTest:testExchangeWithAnyNonceWhichIsUsedWillRevert(bytes32) (runs: 4104, μ: 202877, ~: 202877) +VotingPwoerExchangeTest:testExchangeWithAnyRoleWhoIsNotExchangerWillRevert(address) (runs: 4104, μ: 44206, ~: 44206) +VotingPwoerExchangeTest:testExchangeWithAnySenderWhoIsNotTheSignerWillRevert(address) (runs: 4104, μ: 70231, ~: 70233) +VotingPwoerExchangeTest:testFuzzCalculateBurningAmountFromVotingPower_0_10(uint256) (runs: 4104, μ: 17869, ~: 17187) +VotingPwoerExchangeTest:testFuzzCalculateBurningAmountFromVotingPower_0_110(uint256) (runs: 4104, μ: 17856, ~: 17186) +VotingPwoerExchangeTest:testFuzzCalculateBurningAmountFromVotingPower_100_110(uint256) (runs: 4104, μ: 18594, ~: 18639) +VotingPwoerExchangeTest:testFuzzCalculateBurningAmountFromVotingPower_10_20(uint256) (runs: 4104, μ: 18569, ~: 18615) +VotingPwoerExchangeTest:testFuzzCalculateBurningAmountFromVotingPower_20_30(uint256) (runs: 4104, μ: 18548, ~: 18595) +VotingPwoerExchangeTest:testFuzzCalculateBurningAmountFromVotingPower_30_40(uint256) (runs: 4104, μ: 18618, ~: 18663) +VotingPwoerExchangeTest:testFuzzCalculateBurningAmountFromVotingPower_40_50(uint256) (runs: 4104, μ: 18638, ~: 18683) +VotingPwoerExchangeTest:testFuzzCalculateBurningAmountFromVotingPower_50_60(uint256) (runs: 4104, μ: 18639, ~: 18684) +VotingPwoerExchangeTest:testFuzzCalculateBurningAmountFromVotingPower_60_70(uint256) (runs: 4104, μ: 18616, ~: 18662) +VotingPwoerExchangeTest:testFuzzCalculateBurningAmountFromVotingPower_70_80(uint256) (runs: 4104, μ: 18574, ~: 18618) +VotingPwoerExchangeTest:testFuzzCalculateBurningAmountFromVotingPower_80_90(uint256) (runs: 4104, μ: 18617, ~: 18662) +VotingPwoerExchangeTest:testFuzzCalculateBurningAmountFromVotingPower_90_100(uint256) (runs: 4104, μ: 18618, ~: 18663) +VotingPwoerExchangeTest:testFuzzCalculateIncrementedBurningAmount_0_to_110(uint256) (runs: 4104, μ: 17928, ~: 17258) +VotingPwoerExchangeTest:testFuzzCalculateIncrementedBurningAmount_100_to_110(uint256) (runs: 4104, μ: 17970, ~: 17288) +VotingPwoerExchangeTest:testFuzzCalculateIncrementedBurningAmount_10_to_110(uint256) (runs: 4104, μ: 17999, ~: 17329) +VotingPwoerExchangeTest:testFuzzCalculateIncrementedBurningAmount_20_to_110(uint256) (runs: 4104, μ: 17959, ~: 17288) +VotingPwoerExchangeTest:testFuzzCalculateIncrementedBurningAmount_30_to_110(uint256) (runs: 4104, μ: 17937, ~: 17266) +VotingPwoerExchangeTest:testFuzzCalculateIncrementedBurningAmount_40_to_110(uint256) (runs: 4104, μ: 18003, ~: 17332) +VotingPwoerExchangeTest:testFuzzCalculateIncrementedBurningAmount_50_to_110(uint256) (runs: 4104, μ: 17938, ~: 17265) +VotingPwoerExchangeTest:testFuzzCalculateIncrementedBurningAmount_60_to_110(uint256) (runs: 4104, μ: 17982, ~: 17308) +VotingPwoerExchangeTest:testFuzzCalculateIncrementedBurningAmount_70_to_110(uint256) (runs: 4104, μ: 17961, ~: 17287) +VotingPwoerExchangeTest:testFuzzCalculateIncrementedBurningAmount_80_to_110(uint256) (runs: 4104, μ: 17919, ~: 17244) +VotingPwoerExchangeTest:testFuzzCalculateIncrementedBurningAmount_90_to_110(uint256) (runs: 4104, μ: 17988, ~: 17310) +VotingPwoerExchangeTest:testFuzzCalculateVotingPowerFromBurnedAmount(uint256) (runs: 4104, μ: 20407, ~: 19752) +VotingPwoerExchangeTest:testFuzzCalculateVotingPowerFromBurnedAmount_0_925(uint256) (runs: 4104, μ: 20404, ~: 19731) +VotingPwoerExchangeTest:testFuzzCalculateVotingPowerFromBurnedAmount_12700_19625(uint256) (runs: 4104, μ: 21358, ~: 21399) +VotingPwoerExchangeTest:testFuzzCalculateVotingPowerFromBurnedAmount_19625_28050(uint256) (runs: 4104, μ: 21350, ~: 21402) +VotingPwoerExchangeTest:testFuzzCalculateVotingPowerFromBurnedAmount_28050_37975(uint256) (runs: 4104, μ: 21352, ~: 21401) +VotingPwoerExchangeTest:testFuzzCalculateVotingPowerFromBurnedAmount_3350_7275(uint256) (runs: 4104, μ: 21235, ~: 21270) +VotingPwoerExchangeTest:testFuzzCalculateVotingPowerFromBurnedAmount_37975_49400(uint256) (runs: 4104, μ: 21218, ~: 21251) +VotingPwoerExchangeTest:testFuzzCalculateVotingPowerFromBurnedAmount_49400_62325(uint256) (runs: 4104, μ: 21222, ~: 21271) +VotingPwoerExchangeTest:testFuzzCalculateVotingPowerFromBurnedAmount_62325_76750(uint256) (runs: 4104, μ: 21212, ~: 21252) +VotingPwoerExchangeTest:testFuzzCalculateVotingPowerFromBurnedAmount_7275_12700(uint256) (runs: 4104, μ: 21270, ~: 21330) +VotingPwoerExchangeTest:testFuzzCalculateVotingPowerFromBurnedAmount_76750_92675(uint256) (runs: 4104, μ: 21246, ~: 21275) +VotingPwoerExchangeTest:testFuzzCalculateVotingPowerFromBurnedAmount_925_3350(uint256) (runs: 4104, μ: 21297, ~: 21361) +VotingPwoerExchangeTest:testSetVotingPowerCap(uint256) (runs: 4100, μ: 25451, ~: 25451) +VotingPwoerExchangeTest:testSetVotingPowerCap_revertWhenLowerThanExisting(uint256) (runs: 4100, μ: 18046, ~: 18046) +VotingPwoerExchangeTest:testSetVotingPowerCap_revertWhenNonManagerCalled(address) (runs: 4104, μ: 17759, ~: 17759) \ No newline at end of file diff --git a/README.md b/README.md index 8c3759e..813255e 100644 --- a/README.md +++ b/README.md @@ -161,6 +161,8 @@ No one is allowed to get more voting power than the cap. After the calculation, the function will mint the governance token to the holder and burn the utility token from the holder. +The function also updates the amount of the utility token that the holder has burned in the GovToken contract. + #### Notes - The contract is created from scratch. diff --git a/changelog.md b/changelog.md deleted file mode 100644 index 7598aea..0000000 --- a/changelog.md +++ /dev/null @@ -1,38 +0,0 @@ -# Smart Contracts' Changelog - -## [Unreleased] - -### Added - -- Added the specification of not allowing the default admin to be zero address. - -1. ERC20UpgradeableToken (ERC20) - -- Created using OpenZeppelin Wizard. -- Created using OpenZeppelin upgradeable contracts. - -2. AmbassadorNft (ERC1155) - -- Created using OpenZeppelin Wizard. -- Added some roles and the burning function to it. - -### More Information - -Overall, we changed all the version of solidity into fixed 0.8.24. - -1. ERC20UpgradeableToken - Forked from OpenZeppelin's ERC20 Wizard contract. - -- Allow initializing the contract with a name, symbol, and burner. Including the originally generated code by Wizard of pauser, minter, and the default admin roles. -- Modified the contract to add burner access right and burner to burn tokens. - -2. AmbassadorNft - Forked from OpenZeppelin's ERC1155 Wizard contract. - -- Added new roles of `burner`, `minter`, `uriSetter`, and `admin` to the contract. -- Allowing setting the URI of the token afterwards. -- Allowing burning of the token by the burner role. - -### Fixed - -### Removed diff --git a/src/GovToken.sol b/src/GovToken.sol index 774db8d..6652d80 100644 --- a/src/GovToken.sol +++ b/src/GovToken.sol @@ -23,7 +23,6 @@ contract GovToken is ERC20, ERC20Burnable, AccessControl, ERC20Permit, ERC20Vote // added for recording the amount of utility tokens burned by a specific account mapping(address account => uint256 burnedAmount) public burnedAmountOfUtilToken; - /// votingPowerExchange role is supposed to be only granted to VotingPowerExchange contract constructor( string memory name, string memory symbol, @@ -38,12 +37,13 @@ contract GovToken is ERC20, ERC20Burnable, AccessControl, ERC20Permit, ERC20Vote _grantRole(MINTER_ROLE, minter); _grantRole(BURNER_ROLE, burner); _grantRole(BURNER_ROLE, burner); + // votingPowerExchange role is supposed to be only granted to VotingPowerExchange contract _grantRole(VOTING_POWER_EXCHANGE_ROLE, votingPowerExchange); } // The following functions are overrides required by Solidity. /// @dev this function is intentionally made this way to not allow token transfer - /// @dev instead minting and burning is allowed + /// @dev on the other hand, minting and burning are allowed /// @dev added this function to the original contract /// function _update(address from, address to, uint256 value) internal override(ERC20, ERC20Votes) { @@ -84,15 +84,28 @@ contract GovToken is ERC20, ERC20Burnable, AccessControl, ERC20Permit, ERC20Vote emit burnedAmountOfUtilTokenSet(account, amount); } + /** + * @notice Overrides the clock function to return the current timestamp. + * @return The current timestamp. + */ function clock() public view override returns (uint48) { return uint48(block.timestamp); } + /** + * @notice Overrides the CLOCK_MODE function to return the current timestamp. + * @return The current timestamp. + */ // solhint-disable-next-line func-name-mixedcase function CLOCK_MODE() public pure override returns (string memory) { return "mode=timestamp"; } + /** + * @notice Overrides the nonces function to return the nonce of the owner. + * @param owner The address of the owner. + * @return The nonce of the owner. + */ function nonces(address owner) public view override(ERC20Permit, Nonces) returns (uint256) { return super.nonces(owner); } diff --git a/test/unit/GovToken.t.sol b/test/unit/GovToken.t.sol index 8015a74..29b8cf4 100644 --- a/test/unit/GovToken.t.sol +++ b/test/unit/GovToken.t.sol @@ -295,7 +295,7 @@ contract GovTokenTest is Test { "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ), owner, - address(this), + address(12), 1 ether, 0, deadline @@ -305,13 +305,18 @@ contract GovTokenTest is Test { ) ); - govToken.permit(owner, address(this), 1 ether, deadline, v, r, s); + govToken.permit(owner, address(12), 1 ether, deadline, v, r, s); // check if nonce is incremented after permit assertEq(govToken.nonces(owner), 1, "Nonce should be incremented after permit"); // other user's nonce should still be 0 assertEq(govToken.nonces(user), 0, "Other user's nonce should still be 0"); + // transfer the token to user2 on behalf of owner will fail + vm.prank(address(12)); + vm.expectRevert(GovToken.TokenTransferNotAllowed.selector); + govToken.transferFrom(owner, user2, 1 ether); + // In fact ERC20Permit is technically not used in this contract due to the token's untransferability. } function testDelegateBySig() public { @@ -349,6 +354,64 @@ contract GovTokenTest is Test { assertEq(govToken.delegates(user), address(0), "Other user's delegate should still be address(0)"); } + function testDelegates() public view { + // check the initial delegate of the user + assertEq(govToken.delegates(user), address(0), "Initial delegate should be address(0)"); + + // check the initial delegate of the user2 + assertEq(govToken.delegates(user2), address(0), "Initial delegate should be address(0)"); + + // check the initial delegate of the user3 + assertEq(govToken.delegates(user3), address(0), "Initial delegate should be address(0)"); + } + + function testInitialVotes() public view { + // check the initial votes of the user + assertEq(govToken.getVotes(user), 0, "Initial votes should be 0"); + + // check the initial votes of the user2 + assertEq(govToken.getVotes(user2), 0, "Initial votes should be 0"); + + // check the initial votes of the user3 + assertEq(govToken.getVotes(user3), 0, "Initial votes should be 0"); + } + + function testVotesAfterSelfDelegate() public { + // check the initial votes of the user + assertEq(govToken.getVotes(user), 0, "Initial votes should be 0"); + // test the votes of the user after delegate to himself + vm.startPrank(user); + govToken.delegate(user); + vm.stopPrank(); + + // check the votes of the user + assertEq(govToken.getVotes(user), 100 ether, "Votes should be 100 ether"); + + // check the initial votes of the user3 + assertEq(govToken.getVotes(user3), 0, "Initial votes should be 0"); + } + + function testVotesAfterDelegateToOther() public { + // check the initial votes of the user + assertEq(govToken.getVotes(user), 0, "Initial votes should be 0"); + // check the initial votes of the user2 + assertEq(govToken.getVotes(user2), 0, "Initial votes should be 0"); + + // test the votes of the user after delegate to user2 + vm.prank(user2); + govToken.delegate(user2); + + assertEq(govToken.getVotes(user2), 100 ether, "Votes should be 100 ether"); + + vm.prank(user); + govToken.delegate(user2); + + // check the votes of the user + assertEq(govToken.getVotes(user), 0, "Votes should be 0"); + // check the votes of the user2 + assertEq(govToken.getVotes(user2), 200 ether, "Votes should be 100 ether"); + } + function testClock() public { // set up a timestamp uint256 currentTimestamp = 1678901234; // 2023-03-15 12:33:54 UTC diff --git a/test/unit/VotingPowerExchange.t.sol b/test/unit/VotingPowerExchange.t.sol index 068bd82..3463937 100644 --- a/test/unit/VotingPowerExchange.t.sol +++ b/test/unit/VotingPowerExchange.t.sol @@ -354,6 +354,7 @@ contract VotingPowerExchangeUnitTest is Test { uint256 _amount3 = 40000e18; uint256 votingPowerGot2 = votingPowerExchange.calculateIncrementedVotingPower(_amount3, _amount2); assertEq(votingPowerGot2, 31609918072733333334); + // test the sum of the two voting powers is 99e18 assertEq(votingPowerGot2 + votingPowerGot, 99e18); } @@ -407,6 +408,95 @@ contract VotingPowerExchangeUnitTest is Test { runTestCaseForIncrementedVotingPower(75215 * 1e18, 25 * 1e18, 98 * 1e18, 12); } + /// JavaScript code for reference + /** + * ```javascript + * const PRECISION = 1n * 10n**18n; + * const PRECISION_FIX = 1n * 10n**9n; + * + * function calculateVotingPowerFromBurnedAmount(amount) { + * // calculate 306.25 + 30*x + * const innerValue = 30625n * 10n**16n + 30n * BigInt(amount); + * + * // calculate 2*SQRT(306.25 + 30*x) + * // using a big number to keep precision + * const SQRT_PRECISION = 1e9; + * const sqrtPart = BigInt(Math.floor(2 * Math.sqrt(Number(innerValue)) * SQRT_PRECISION)) * PRECISION_FIX / BigInt(SQRT_PRECISION); + * + * // calculate (2*SQRT(306.25+30*x)-5)/30 - 1 + * const result = (sqrtPart - 5n * PRECISION) / 30n - PRECISION; + * + * return result > 0n ? result : 0n; + * } + * + * function calculateIncrementedVotingPower(incrementedAmount, currentBurnedAmount) { + * const newTotal = calculateVotingPowerFromBurnedAmount(BigInt(incrementedAmount) + BigInt(currentBurnedAmount)); + * const current = calculateVotingPowerFromBurnedAmount(BigInt(currentBurnedAmount)); + * return newTotal - current; + * } + * + * // test case from javascript + * console.log(calculateIncrementedVotingPower(3350n * 10n**18n, 0n)); + * // 20000000000000000000n + * console.log(calculateIncrementedVotingPower(1400n * 10n**18n, 1950n * 10n**18n)); + * // 5000000000000000000n + * console.log(calculateIncrementedVotingPower(3040n * 10n**18n, 0n)); + * // 19000000000000000000n + * console.log(calculateIncrementedVotingPower(3140n * 10n**18n, 0n)); + * // 19000000000000000000n + * console.log(calculateIncrementedVotingPower(3140n * 10n**18n, 0n)); + * // 19327912562431395976n + * console.log(calculateIncrementedVotingPower(925n * 10n**18n, 25n * 10n ** 18n)); + * // 9148269381662452394n + * + * function sqrtBigInt(value) { + * if (value < 0n) throw new Error("Cannot compute square root of negative number"); + * if (value === 0n) return 0n; + * + * let x = value; + * let y = (value / 2n) + 1n; // 初始猜测 + * while (y < x) { + * x = y; + * y = (value / y + y) / 2n; // 牛顿迭代 + * } + * return x; + * } + * ``` + */ + // function testCalculateIncrementedVotingPowerWithJavaScript() public view { + // // test the function when the result is 20000000000000000000n in javascript + // uint256 amount = 3350 * 1e18; + // uint256 currentBurnedAmount = 0 * 1e18; + // uint256 expectedIncrease = 20000000000000000000; + // runTestCaseForIncrementedVotingPower(amount, currentBurnedAmount, expectedIncrease, 1); + + // // test the function when the result is 19000000000000000000n in javascript + // amount = 3040 * 1e18; + // currentBurnedAmount = 0 * 1e18; + // expectedIncrease = 19000000000000000000; + // runTestCaseForIncrementedVotingPower(amount, currentBurnedAmount, expectedIncrease, 2); + + // // test the function when the result is 5000000000000000000n in javascript + // amount = 1400 * 1e18; + // currentBurnedAmount = 1950 * 1e18; + // expectedIncrease = 5000000000000000000; + // runTestCaseForIncrementedVotingPower(amount, currentBurnedAmount, expectedIncrease, 2); + // } + + // function testCalculateIncrementedVotingPowerWithJavaScript2() public view { + // // test the function when the result is 19327912562431395976n in javascript + // amount = 3140 * 1e18; + // currentBurnedAmount = 0 * 1e18; + // expectedIncrease = 19327912562431395976; + // runTestCaseForIncrementedVotingPower(amount, currentBurnedAmount, expectedIncrease, 2); + + // // test the function when the result is 9148269381662452394n in javascript + // amount = 925 * 1e18; + // currentBurnedAmount = 25 * 1e18; + // expectedIncrease = 9148269381662452394; + // runTestCaseForIncrementedVotingPower(amount, currentBurnedAmount, expectedIncrease, 2); + // } + // Helper function to run individual test cases // Parameters: // - amount: The amount of tokens to be burned