From 168ba92f3b4d23cee2dee9f2634198b6b2388811 Mon Sep 17 00:00:00 2001 From: gozzy Date: Sun, 9 Apr 2023 12:25:37 +0000 Subject: [PATCH] initialise --- .gitattributes | 1 + .gitmodules | 3 ++ README.md | 8 +++ foundry.toml | 7 +++ package.json | 15 ++++++ src/Proposal.sol | 9 ++++ src/interfaces/IGovernance.sol | 20 ++++++++ src/proprietary/Mock.sol | 32 ++++++++++++ src/proprietary/Parameters.sol | 3 ++ test/Proposal.t.sol | 92 ++++++++++++++++++++++++++++++++++ 10 files changed, 190 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitmodules create mode 100644 README.md create mode 100644 foundry.toml create mode 100644 package.json create mode 100644 src/Proposal.sol create mode 100644 src/interfaces/IGovernance.sol create mode 100644 src/proprietary/Mock.sol create mode 100644 src/proprietary/Parameters.sol create mode 100644 test/Proposal.t.sol diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..7cc88f0 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.sol linguist-language=Solidity \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..888d42d --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/forge-std"] + path = lib/forge-std + url = https://github.com/foundry-rs/forge-std diff --git a/README.md b/README.md new file mode 100644 index 0000000..619d1af --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +## Requirements + +* NodeJS +* Foundryup + +## Testing + +`npm run test` \ No newline at end of file diff --git a/foundry.toml b/foundry.toml new file mode 100644 index 0000000..c5ba031 --- /dev/null +++ b/foundry.toml @@ -0,0 +1,7 @@ +[profile.default] +src = 'src' +out = 'out' +libs = ["node_modules", "lib"] +chain_id = 1 + +# See more config options https://github.com/foundry-rs/foundry/tree/master/config \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..76a9f01 --- /dev/null +++ b/package.json @@ -0,0 +1,15 @@ +{ + "name": "relayer-penalty-proposal", + "version": "1.0.0", + "description": "", + "main": "index.js", + "directories": { + "lib": "lib", + "test": "test" + }, + "scripts": { + "test": "forge test -vvvvv --fork-url https://api.securerpc.com/v1 --block-number 16216695" + }, + "author": "", + "license": "ISC" +} diff --git a/src/Proposal.sol b/src/Proposal.sol new file mode 100644 index 0000000..7d37638 --- /dev/null +++ b/src/Proposal.sol @@ -0,0 +1,9 @@ +pragma solidity 0.8.1; + +import "./interfaces/IERC20.sol"; + +contract Proposal { + + function executeProposal() external { } + +} diff --git a/src/interfaces/IGovernance.sol b/src/interfaces/IGovernance.sol new file mode 100644 index 0000000..9934dc4 --- /dev/null +++ b/src/interfaces/IGovernance.sol @@ -0,0 +1,20 @@ +pragma solidity ^0.8.1; + +interface IGovernance { + + function propose(address target, string memory description) external returns (uint256); + + function castVote(uint256 proposalId, bool support) external; + + function execute(uint256 proposalId) external payable; + + function lock( + address owner, + uint256 amount, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external; + +} \ No newline at end of file diff --git a/src/proprietary/Mock.sol b/src/proprietary/Mock.sol new file mode 100644 index 0000000..1cbe61f --- /dev/null +++ b/src/proprietary/Mock.sol @@ -0,0 +1,32 @@ +pragma solidity ^0.8.1; + +contract Mock { + + uint256 constant TEST_PRIVATE_KEY_ONE = 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80; + uint256 constant TEST_PRIVATE_KEY_TWO = 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d; + address constant TEST_ADDRESS_ONE = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266; + address constant TEST_ADDRESS_TWO = 0x70997970C51812dc3A010C7d01b50e0d17dc79C8; + + uint256 constant PROPOSAL_DURATION = 7 days; + uint256 constant PROPOSAL_THRESHOLD = 25000 ether; + string constant PROPOSAL_DESCRIPTION = "Proposal #15: Renumeration and accounting"; + + address constant VERIFIER_ADDRESS = 0x77777FeDdddFfC19Ff86DB637967013e6C6A116C; + + bytes32 constant public PERMIT_TYPEHASH = keccak256( + "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" + ); + + bytes32 constant EIP712_DOMAIN = keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256(bytes("TornadoCash")), + keccak256(bytes("1")), + 1, + VERIFIER_ADDRESS + ) + ); + + uint16 constant PERMIT_FUNC_SELECTOR = uint16(0x1901); + +} \ No newline at end of file diff --git a/src/proprietary/Parameters.sol b/src/proprietary/Parameters.sol new file mode 100644 index 0000000..1b06264 --- /dev/null +++ b/src/proprietary/Parameters.sol @@ -0,0 +1,3 @@ +pragma solidity 0.8.1; + +contract Parameters { } diff --git a/test/Proposal.t.sol b/test/Proposal.t.sol new file mode 100644 index 0000000..170d4bd --- /dev/null +++ b/test/Proposal.t.sol @@ -0,0 +1,92 @@ +pragma solidity ^0.8.1; + +import "../src/interfaces/IGovernance.sol"; +import "../src/interfaces/IERC20.sol"; + +import "../src/proprietary/Parameters.sol"; +import "../src/proprietary/Mock.sol"; + +import "../src/Proposal.sol"; +import "forge-std/Test.sol"; + +contract ProposalTest is Test, Mock, Parameters { + + function testProposal() public { + checkParameters(); + + uint256 proposalId = voteAndCreateProposal(address(new Proposal())); + + IGovernance(governanceAddress).execute(proposalId); + } + + function voteAndCreateProposal(address proposalAddress) public returns (uint256) { + retrieveAndLockBalance(TEST_PRIVATE_KEY_ONE, TEST_ADDRESS_ONE, PROPOSAL_THRESHOLD); + retrieveAndLockBalance(TEST_PRIVATE_KEY_TWO, TEST_ADDRESS_TWO, 1 ether); + + /* ----------PROPOSER------------ */ + vm.startPrank(TEST_ADDRESS_ONE); + + uint256 proposalId = IGovernance(governanceAddress).propose( + proposalAddress, + PROPOSAL_DESCRIPTION + ); + + // TIME-TRAVEL + vm.warp(block.timestamp + 6 hours); + + IGovernance(governanceAddress).castVote(proposalId, true); + + vm.stopPrank(); + /* ------------------------------ */ + + /* -------------VOTER-------------*/ + vm.startPrank(TEST_ADDRESS_TWO); + IGovernance(governanceAddress).castVote(proposalId, true); + vm.stopPrank(); + /* ------------------------------ */ + + // TIME-TRAVEL + vm.warp(block.timestamp + PROPOSAL_DURATION); + + return proposalId; + } + + function retrieveAndLockBalance(uint256 privateKey, address voter, uint256 amount) internal { + uint256 lockTimestamp = block.timestamp + PROPOSAL_DURATION; + bytes32 messageHash = keccak256( + abi.encodePacked( + PERMIT_FUNC_SELECTOR, + EIP712_DOMAIN, + keccak256( + abi.encode( + PERMIT_TYPEHASH, + voter, + governanceAddress, + amount, + 0, + lockTimestamp + ) + ) + ) + ); + + /* ----------GOVERNANCE------- */ + vm.startPrank(governanceAddress); + IERC20(tokenAddress).transfer(voter, amount); + vm.stopPrank(); + /* ----------------------------*/ + + (uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey, messageHash); + + /* ----------VOTER------------ */ + vm.startPrank(voter); + IGovernance(governanceAddress).lock(voter, amount, lockTimestamp, v, r, s); + vm.stopPrank(); + /* ----------------------------*/ + } + + function checkParameters() internal {} + + function checkResults() internal {} + +}