Skip to content

Commit

Permalink
add signature generation test helper and changed importing directory,…
Browse files Browse the repository at this point in the history
… remappings.
  • Loading branch information
thurendous committed Sep 6, 2024
1 parent 5c77691 commit 37c2033
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 16 deletions.
1 change: 1 addition & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ ast = true
build_info = true
extra_output = ["storageLayout"]
solc = "0.8.24"
remappings = ["forge-std/=lib/forge-std/src/"]

# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
14 changes: 8 additions & 6 deletions remappings.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/
@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/
ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/
erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/
forge-std/=lib/forge-std/src/
@openzeppelin/openzeppelin-foundry-upgrades/=lib/openzeppelin-foundry-upgrades/src
@openzeppelin/upgradeable/lib=lib/openzeppelin-contracts-upgradeable/lib/
@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/
@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/
ds-test/=lib/openzeppelin-contracts-upgradeable/lib/forge-std/lib/ds-test/src/
erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/
openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/
openzeppelin-contracts/=lib/openzeppelin-contracts/
openzeppelin-foundry-upgrades/=lib/openzeppelin-foundry-upgrades/src/
solidity-stringutils/=lib/openzeppelin-foundry-upgrades/lib/solidity-stringutils/
5 changes: 3 additions & 2 deletions script/DeployContracts.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
pragma solidity 0.8.24;

import {console, Script} from "forge-std/Script.sol";
import {Upgrades, UnsafeUpgrades} from "@openzeppelin/openzeppelin-foundry-upgrades/Upgrades.sol";
import {IAccessControl} from "@openzeppelin/upgradeable/lib/openzeppelin-contracts/contracts/access/IAccessControl.sol";
import {Upgrades, UnsafeUpgrades} from "openzeppelin-foundry-upgrades/Upgrades.sol";
import {IAccessControl} from
"openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/access/IAccessControl.sol";
import {ERC20UpgradeableTokenV1} from "src/ERC20UpgradeableTokenV1.sol";
import {VotingPowerExchange} from "src/VotingPowerExchange.sol";
import {GovToken} from "src/GovToken.sol";
Expand Down
2 changes: 1 addition & 1 deletion src/GovToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pragma solidity ^0.8.20;
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {ERC20Burnable} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";
import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
import {ERC20Permit, Nonces} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
import {ERC20Votes} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol";

/// @custom:security-contact [email protected]
Expand Down
4 changes: 2 additions & 2 deletions src/VotingPowerExchange.sol
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ contract VotingPowerExchange is AccessControl, EIP712 {
// voting power cap for limiting the voting power
uint256 private votingPowerCap;

/// constructor function of the contract.
/// @param _govToken The address of the GovToken contract
/// @param _utilityToken The address of the ERC20 token contract
/// @param defaultAdmin The address of the default admin
Expand Down Expand Up @@ -89,7 +88,8 @@ contract VotingPowerExchange is AccessControl, EIP712 {
* @param sender The address of the user who wants to exchange utilityToken for voting power token.
* @param amount The amount of utilityToken to exchange.
* @param nonce The nonce to prevent replay attacks.
* @param signature The signature of the user to validate the exchange intention.
* @param expiration The expiration time of the signature.
* @param signature The signature of the user to validate the voting power exchanging intention.
*/
function exchange(address sender, uint256 amount, bytes32 nonce, uint256 expiration, bytes calldata signature)
external
Expand Down
40 changes: 37 additions & 3 deletions test/integration/VotingPowerExchange.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ contract VotingPwoerExchangeTest is Test {
address public participant = makeAddr("levelUpper2");
address public participant2;

// private key
uint256 public default_anvil_key2 = 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d;

// deploy scripts
function setUp() public {
dc = new DeployContracts();
Expand Down Expand Up @@ -183,6 +186,16 @@ contract VotingPwoerExchangeTest is Test {
//////////////////////////////////////////////
///// Core tests for VotingPowerExchange /////
//////////////////////////////////////////////
function testConstructorOfVotingPowerExchange() public {
vm.expectRevert(VotingPowerExchange.VotingPowerExchange__DefaultAdminCannotBeZero.selector);
new VotingPowerExchange(address(utilityToken), address(govToken), address(0), manager, exchanger);

VotingPowerExchange vpe =
new VotingPowerExchange(address(utilityToken), address(govToken), admin, manager, exchanger);
assertTrue(address(vpe) != address(0));
assertEq(vpe.getVotingPowerCap(), 100 * 1e18);
}

function teestBasicVotingPowerExchangeInfo() public view {
(address _utilityToken, address _govToken) = votingPowerExchange.getTokenAddresses();
assertEq(_govToken, address(govToken));
Expand Down Expand Up @@ -229,6 +242,10 @@ contract VotingPwoerExchangeTest is Test {
vm.prank(manager);
vm.expectRevert(VotingPowerExchange.VotingPowerExchange__LevelIsLowerThanExisting.selector);
votingPowerExchange.setVotingPowerCap(99 * 1e18);

vm.prank(manager);
vm.expectRevert(VotingPowerExchange.VotingPowerExchange__LevelIsLowerThanExisting.selector);
votingPowerExchange.setVotingPowerCap(100 * 1e18);
}

// this test only run the test for the calculation of increased voting power function
Expand Down Expand Up @@ -260,15 +277,15 @@ contract VotingPwoerExchangeTest is Test {
// 1000 | 100 -> 2.316 voting power
// 100 | 100 -> 0.4142 voting power
function testCalculationOfIncreasedVotingPowerWhenCurrentIsNotZero() public view {
// when you exchange 1_000_000 utility token, you will get 100 voting power
// when you exchange 2_000_000 utility token and burned token is currently 1000 * 1e18, you will get 138 voting power
uint256 increasedVotingPower = votingPowerExchange.calculateIncreasedVotingPower(2000000 * 1e18, 1000 * 1e18);
assertTrue(increasedVotingPower < 1383 * 1e17);
assertTrue(increasedVotingPower > 1382 * 1e17);
// when you exchange 1_500_000 utility token, you will get 100 voting power
// when you exchange 1_500_000 utility token with current burned token as 1000 * 1e18, you will get 119 voting power
increasedVotingPower = votingPowerExchange.calculateIncreasedVotingPower(1500000 * 1e18, 1000 * 1e18);
assertTrue(increasedVotingPower < 1194 * 1e17);
assertTrue(increasedVotingPower > 1193 * 1e17);
// when you exchange 1_000_000 utility token, you will get 100 voting power
// when you exchange 1_000_000 utility token with current burned tokken as 100 * 1e18, you will get 99 voting power
increasedVotingPower = votingPowerExchange.calculateIncreasedVotingPower(1000000 * 1e18, 100 * 1e18);
assertTrue(increasedVotingPower < 991 * 1e17);
assertTrue(increasedVotingPower > 99 * 1e18);
Expand Down Expand Up @@ -306,4 +323,21 @@ contract VotingPwoerExchangeTest is Test {
assertTrue(requiredAmount < 810_001 * 1e18);
assertTrue(requiredAmount > 809_999 * 1e18);
}

function testCalculateRequiredAmountToBeBurnedWhenCurrentIsNotZero() public view {
// when you exchange 7 voting power with current burned token as 900 * 1e18, you need to burn 7 utility token
uint256 requiredAmount = votingPowerExchange.calculateRequiredAmountToBeBurned(7 * 1e18, 900 * 1e18);
assertEq(requiredAmount, 9100 * 1e18);
// when you exchange 10 voting power with token burned as 3600 * 1e18, you need to burn 22000 utility token
requiredAmount = votingPowerExchange.calculateRequiredAmountToBeBurned(10 * 1e18, 3_600 * 1e18);
assertEq(requiredAmount, 22_000 * 1e18);
// when you exchange 5 voting power with token burned as 22500 * 1e18, you need to burn 17500 utility token
requiredAmount = votingPowerExchange.calculateRequiredAmountToBeBurned(5 * 1e18, 22_500 * 1e18);
assertEq(requiredAmount, 17_500 * 1e18);
// when you exchange 20 voting power with token burned as 16_900 * 1e18, you need to burn 92_000 utility token
requiredAmount = votingPowerExchange.calculateRequiredAmountToBeBurned(20 * 1e18, 16_900 * 1e18);
assertEq(requiredAmount, 92_000 * 1e18);
}

/////// Exchange tests ///////
}
38 changes: 38 additions & 0 deletions test/integration/utils/VotingPowerExchangeTestHelper.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.24;

import {DeployContracts, DeploymentResult} from "script/DeployContracts.s.sol";
import {Test, console} from "forge-std/Test.sol";

import {VotingPowerExchange} from "src/VotingPowerExchange.sol";

contract VotingPowerExchangeTestHelper is Test {
bytes32 private constant _EXCHANGE_TYPEHASH =
keccak256("Exchange(address sender,uint256 amount,bytes32 nonce,uint256 expiration)");

function generateSignatureFromPrivateKey(uint256 privateKey, uint256 amount, uint256 nonce, uint256 expiration)
public
view
returns (bytes memory)
{
address sender = address(uint160(privateKey));
bytes32 structHash = keccak256(abi.encode(_EXCHANGE_TYPEHASH, sender, amount, nonce, expiration));

bytes32 domainSeparator = keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes("VotingPowerExchange")),
keccak256(bytes("1")),
block.chainid,
address(this)
)
);

bytes32 hash = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));

(uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey, hash);

return abi.encodePacked(r, s, v);
}
}
5 changes: 3 additions & 2 deletions test/unit/ERC20UpgradeableTokenV1.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
pragma solidity 0.8.24;

import {Test, console} from "forge-std/Test.sol";
import {UnsafeUpgrades, Upgrades} from "@openzeppelin/openzeppelin-foundry-upgrades/Upgrades.sol";
import {IAccessControl} from "@openzeppelin/upgradeable/lib/openzeppelin-contracts/contracts/access/IAccessControl.sol";
import {UnsafeUpgrades, Upgrades} from "openzeppelin-foundry-upgrades/Upgrades.sol";
import {IAccessControl} from
"openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/access/IAccessControl.sol";
import {ERC20UpgradeableTokenV1} from "src/ERC20UpgradeableTokenV1.sol";
import {ERC20UpgradeableTokenV2} from "../mocks/ERC20UpgradeableTokenV2.sol";

Expand Down

0 comments on commit 37c2033

Please sign in to comment.