From 38563d7f0d84c35c716fe86ba279170919e67f09 Mon Sep 17 00:00:00 2001 From: Mercedes Date: Thu, 18 Apr 2024 18:06:24 -0300 Subject: [PATCH 1/4] Create PermitSigUtils.sol --- test/foundry/utils/PermitSigUtils.sol | 34 +++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 test/foundry/utils/PermitSigUtils.sol diff --git a/test/foundry/utils/PermitSigUtils.sol b/test/foundry/utils/PermitSigUtils.sol new file mode 100644 index 00000000..a8a72a6a --- /dev/null +++ b/test/foundry/utils/PermitSigUtils.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.13; + +contract PermitSigUtils { + bytes32 internal DOMAIN_SEPARATOR; + + constructor(bytes32 _DOMAIN_SEPARATOR) { + DOMAIN_SEPARATOR = _DOMAIN_SEPARATOR; + } + + // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); + bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; + + struct Permit { + address owner; + address spender; + uint256 value; + uint256 nonce; + uint256 deadline; + } + + // computes the hash of a permit + function getStructHash(Permit memory _permit) internal pure returns (bytes32) { + return + keccak256( + abi.encode(PERMIT_TYPEHASH, _permit.owner, _permit.spender, _permit.value, _permit.nonce, _permit.deadline) + ); + } + + // computes the hash of the fully encoded EIP-712 message for the domain, which can be used to recover the signer + function getTypedDataHash(Permit memory _permit) public view returns (bytes32) { + return keccak256(abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR, getStructHash(_permit))); + } +} From d1ca1679ce5f7f27793bd2f27d99c9a1aae8115a Mon Sep 17 00:00:00 2001 From: Mercedes Date: Thu, 18 Apr 2024 18:06:36 -0300 Subject: [PATCH 2/4] Update 03_Erc20Enforcer.t.sol --- test/foundry/deploy/03_Erc20Enforcer.t.sol | 74 ++++++++++++++++++++-- 1 file changed, 67 insertions(+), 7 deletions(-) diff --git a/test/foundry/deploy/03_Erc20Enforcer.t.sol b/test/foundry/deploy/03_Erc20Enforcer.t.sol index 95289dbc..c38614aa 100644 --- a/test/foundry/deploy/03_Erc20Enforcer.t.sol +++ b/test/foundry/deploy/03_Erc20Enforcer.t.sol @@ -8,6 +8,7 @@ import {SampleERC20} from "../../../src/token/SampleERC20.sol"; import {ERC20Mock} from "../../../src/mock/ERC20Mock.sol"; import {Admin} from "../../../src/abstract/Admin.sol"; import {ERC20} from "../../../src/interface/ERC20.sol"; +import {PermitSigUtils} from "../utils/PermitSigUtils.sol"; contract Erc20Enforcer is Test { event Transfer(address indexed _from, address indexed _to, uint256 _value); @@ -20,8 +21,10 @@ contract Erc20Enforcer is Test { SampleERC20 sampleERC20; ERC20Mock erc20Mock; Admin admin; + PermitSigUtils permitSigUtils; uint16 tokenDecimals = 18; - address deployer = vm.addr(0xff22437ccbedfffafa93a9f1da2e8c19c1711052799acf3b58ae5bebb5c6bd7b); + uint256 privateKeyDeployer = 0xff22437ccbedfffafa93a9f1da2e8c19c1711052799acf3b58ae5bebb5c6bd7b; + address deployer = vm.addr(privateKeyDeployer); address alice = vm.addr(1); address bob = vm.addr(2); uint256 initialValue = 1; @@ -31,8 +34,8 @@ contract Erc20Enforcer is Test { bytes zeroBytes = bytes(abi.encode("0x0000000000000000000000000000000000000000")); bytes32 zeroSignature = bytes32(abi.encode(0x0000000000000000000000000000000000000000000000000000000000000000)); bytes32 signature = bytes32(abi.encode(0x1111111111111111111111111111111111111111111111111111111111111111)); - bytes32 signature2 = bytes32(abi.encode(0x353535353535353535353535353535353535353535353535353535353535353)); - bytes32 signature3 = bytes32(abi.encode(0x686868686868686868686868686868686868686868686868686868686868686)); + bytes32 signature2 = bytes32(abi.encode(0x35353535353535353535353535353535353535353535353535353535353535)); + bytes32 signature3 = bytes32(abi.encode(0x68686868686868686868686868686868686868686868686868686868686868)); uint256 badDeadLine; uint256 goodDeadLine; @@ -45,6 +48,27 @@ contract Erc20Enforcer is Test { admin = Admin(payable(Constants.getHolographFactoryProxy())); badDeadLine = uint256(block.timestamp) - 1; goodDeadLine = uint256(block.timestamp); + permitSigUtils = new PermitSigUtils(holographERC20.DOMAIN_SEPARATOR()); + } + + function buildDomainSeparator( + string memory name, + string memory version, + address contractAddress + ) public view returns (bytes32) { + bytes32 nameHash = keccak256(bytes(name)); + bytes32 versionHash = keccak256(bytes(version)); + bytes32 typeHash = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); + return + keccak256( + abi.encodePacked( + typeHash, + nameHash, + versionHash, + uint256(block.chainid), + address(Constants.getHolographERC20()) + ) + ); } function mintToAlice() public { @@ -599,7 +623,14 @@ contract Erc20Enforcer is Test { * Permit */ - //TODO buildDomainSeperator + function testCheckDomainSeparator() public { + // TODO Check + vm.skip(true); + assertEq( + holographERC20.DOMAIN_SEPARATOR(), + buildDomainSeparator("Sample ERC20 Token", "1", address(holographERC20)) + ); + } function testPermitZeroNonce() public { assertEq(holographERC20.nonces(alice), 0); @@ -626,15 +657,36 @@ contract Erc20Enforcer is Test { holographERC20.permit(deployer, alice, initialValue, goodDeadLine, uint8(0x04), zeroSignature, zeroSignature); } - //TODO not revert whit invalid signature function testPermitInvalidSignatureRevert() public { - vm.skip(true); vm.expectRevert("ERC20: invalid signature"); vm.prank(deployer); holographERC20.permit(deployer, alice, initialValue, goodDeadLine, uint8(0x1b), signature2, signature3); } - //TODO add sucess Permit + function testValidSignature() public { + PermitSigUtils.Permit memory permit = PermitSigUtils.Permit({ + owner: deployer, + spender: alice, + value: maxValue, + nonce: holographERC20.nonces(alice), + deadline: goodDeadLine + }); + bytes32 digest = permitSigUtils.getTypedDataHash(permit); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKeyDeployer, digest); + vm.expectEmit(true, true, false, true); + emit Approval(deployer, alice, maxValue); + holographERC20.permit(permit.owner, permit.spender, permit.value, permit.deadline, v, r, s); + } + + function testPermitAllowance() public { + testValidSignature(); + assertEq(holographERC20.allowance(deployer, alice), maxValue); + } + + function testPermitNonces() public { + testValidSignature(); + assertEq(holographERC20.nonces(deployer), 1); + } /* * ERC20 TEST @@ -673,6 +725,14 @@ contract Erc20Enforcer is Test { admin.adminCall(address(holographERC20), data); } + function testTransferOwnership() public { + testErc20DeployerTransferOwner(); + vm.expectEmit(true, true, false, true); + emit OwnershipTransferred(address(deployer), address(admin)); + vm.prank(deployer); + holographERC20.setOwner(address(admin)); + } + /* * ERC20 TEST * Admin From 7c8fa561e597c0598b05b43380445c47ff2e211c Mon Sep 17 00:00:00 2001 From: Mercedes Date: Fri, 19 Apr 2024 14:25:21 -0300 Subject: [PATCH 3/4] Update 03_Erc20Enforcer.t.sol --- test/foundry/deploy/03_Erc20Enforcer.t.sol | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/foundry/deploy/03_Erc20Enforcer.t.sol b/test/foundry/deploy/03_Erc20Enforcer.t.sol index c38614aa..5674b46d 100644 --- a/test/foundry/deploy/03_Erc20Enforcer.t.sol +++ b/test/foundry/deploy/03_Erc20Enforcer.t.sol @@ -379,11 +379,13 @@ contract Erc20Enforcer is Test { function testTransferFromZeroAddressRevert() public { vm.expectRevert("ERC20: amount exceeds allowance"); + vm.prank(deployer); holographERC20.transferFrom(zeroAddress, alice, maxValue); } function testTransferFromNotAprrovalAddressRevert() public { vm.expectRevert("ERC20: amount exceeds allowance"); + vm.prank(alice); holographERC20.transferFrom(deployer, alice, maxValue); } @@ -531,7 +533,7 @@ contract Erc20Enforcer is Test { emit Transfer(address(deployer), address(alice), initialValue); vm.prank(alice); holographERC20.transferFrom(address(deployer), address(alice), initialValue); - //check allowance alice = 0 + //check allowance alice = 0. A separate test should be done to verify the decrease in alowance. assertEq(holographERC20.allowance(deployer, alice), 0); } @@ -606,6 +608,7 @@ contract Erc20Enforcer is Test { function testBurnFromNotApproveRevert() public { vm.expectRevert("ERC20: amount exceeds allowance"); + vm.prank(alice); holographERC20.burnFrom(deployer, initialValue); } From 8e747be240c810cbb4321c9af3ec7e978b904d02 Mon Sep 17 00:00:00 2001 From: Mercedes Date: Mon, 22 Apr 2024 14:02:19 -0300 Subject: [PATCH 4/4] fix function testSupportinterface() --- test/foundry/deploy/03_Erc20Enforcer.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/foundry/deploy/03_Erc20Enforcer.t.sol b/test/foundry/deploy/03_Erc20Enforcer.t.sol index 5674b46d..d4464b51 100644 --- a/test/foundry/deploy/03_Erc20Enforcer.t.sol +++ b/test/foundry/deploy/03_Erc20Enforcer.t.sol @@ -106,7 +106,7 @@ contract Erc20Enforcer is Test { */ function testSupportinterface() public { - bytes4 selector = holographERC20.totalSupply.selector; + bytes4 selector = holographERC20.supportsInterface.selector; holographERC20.supportsInterface(selector); }