Start testing contracts
Signed-off-by: AlienTornadosaurusHex <>
This commit is contained in:
parent
a8e09194ec
commit
827e1d6991
1
.env.example
Normal file
1
.env.example
Normal file
@ -0,0 +1 @@
|
||||
MAINNET_RPC_URL=
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -4,3 +4,7 @@ node_modules/
|
||||
.env
|
||||
.gitsigners
|
||||
.trash
|
||||
yarn-error.log
|
||||
yarn.lock
|
||||
cache_hardhat
|
||||
artifacts
|
@ -5,10 +5,11 @@ out = 'out'
|
||||
libs = ["node_modules", "lib"]
|
||||
|
||||
# Compiler
|
||||
evm_version = 'shanghai'
|
||||
auto_detect_solc = true
|
||||
via_ir = true
|
||||
optimizer = true
|
||||
optimizer-runs = 1
|
||||
optimizer = true
|
||||
via_ir = true
|
||||
|
||||
# Network
|
||||
chain_id = 1
|
||||
@ -19,6 +20,9 @@ verbosity = 2
|
||||
|
||||
# Remappings
|
||||
remappings = [
|
||||
'src/=src/',
|
||||
'base/=src/base/',
|
||||
'common/=src/common/',
|
||||
'ds-test/=lib/ds-test/src/',
|
||||
'solmate/=lib/solmate/src/',
|
||||
'forge-std/=lib/forge-std/src/',
|
||||
|
10
package.json
10
package.json
@ -9,15 +9,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "chmod +x script/* && ./script/setup.sh",
|
||||
"build": "chmod +x script/* && ./script/setup.sh",
|
||||
"prettier": "prettier --write 'src/**/*.sol'",
|
||||
"prettier:list": "prettier --list-different 'src/**/*.sol'",
|
||||
"prettier:check": "prettier --check 'src/**/*.sol'",
|
||||
"solhint": "solhint --config ./.solhint.json 'src/**/*.sol' --fix",
|
||||
"solhint:check": "solhint --config ./.solhint.json 'src/**/*.sol'",
|
||||
"lint": "npm run prettier && npm run solhint",
|
||||
"lint:check": "npm run prettier:check && npm run solhint:check",
|
||||
"test": "forge test"
|
||||
"build": "chmod +x script/* && ./script/setup.sh"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier": "^2.5.1",
|
||||
|
27
src/base/TornadoProposal.sol
Normal file
27
src/base/TornadoProposal.sol
Normal file
@ -0,0 +1,27 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.6.12;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
|
||||
import { IGovernance } from "common/interfaces/IGovernance.sol";
|
||||
import { IGnosisSafe } from "common/interfaces/IGnosisSafe.sol";
|
||||
|
||||
import { TornadoAddresses } from "common/TornadoAddresses.sol";
|
||||
|
||||
abstract contract TornadoProposal is TornadoAddresses {
|
||||
function executeProposal() public virtual;
|
||||
|
||||
function getMultisig() internal pure returns (IGnosisSafe) {
|
||||
return IGnosisSafe(getMultisigAddress());
|
||||
}
|
||||
|
||||
function getTornToken() internal pure returns (IERC20) {
|
||||
return IERC20(getTornTokenAddress());
|
||||
}
|
||||
|
||||
function getGovernance() internal pure returns (IGovernance) {
|
||||
return IGovernance(getGovernanceProxyAddress());
|
||||
}
|
||||
}
|
30
src/common/TornadoAddresses.sol
Normal file
30
src/common/TornadoAddresses.sol
Normal file
@ -0,0 +1,30 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.6.12;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract TornadoAddresses {
|
||||
function getENSAddress() internal pure returns (address) {
|
||||
return 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e;
|
||||
}
|
||||
|
||||
function getTornTokenAddress() internal pure returns (address) {
|
||||
return 0x77777FeDdddFfC19Ff86DB637967013e6C6A116C;
|
||||
}
|
||||
|
||||
function getMultisigAddress() internal pure returns (address) {
|
||||
return 0xb04E030140b30C27bcdfaafFFA98C57d80eDa7B4;
|
||||
}
|
||||
|
||||
function getGovernanceProxyAddress() internal pure returns (address) {
|
||||
return 0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce;
|
||||
}
|
||||
|
||||
function getStakingProxyAddress() internal pure returns (address) {
|
||||
return 0x5B3f656C80E8ddb9ec01Dd9018815576E9238c29;
|
||||
}
|
||||
|
||||
function getRegistryProxyAddress() internal pure returns (address) {
|
||||
return 0x58E8dCC13BE9780fC42E8723D8EaD4CF46943dF2;
|
||||
}
|
||||
}
|
85
src/common/interfaces/IGnosisSafe.sol
Normal file
85
src/common/interfaces/IGnosisSafe.sol
Normal file
@ -0,0 +1,85 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.6.12;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
interface IGnosisSafe {
|
||||
enum Operation {
|
||||
Call,
|
||||
DelegateCall
|
||||
}
|
||||
|
||||
function NAME() external view returns (string memory);
|
||||
|
||||
function VERSION() external view returns (string memory);
|
||||
|
||||
function nonce() external view returns (uint256);
|
||||
|
||||
function domainSeparator() external view returns (bytes32);
|
||||
|
||||
function signedMessages(bytes32) external view returns (uint256);
|
||||
|
||||
function approvedHashes(address, bytes32) external view returns (uint256);
|
||||
|
||||
function setup(
|
||||
address[] calldata _owners,
|
||||
uint256 _threshold,
|
||||
address to,
|
||||
bytes calldata data,
|
||||
address fallbackHandler,
|
||||
address paymentToken,
|
||||
uint256 payment,
|
||||
address payable paymentReceiver
|
||||
) external;
|
||||
|
||||
function execTransaction(
|
||||
address to,
|
||||
uint256 value,
|
||||
bytes calldata data,
|
||||
Operation operation,
|
||||
uint256 safeTxGas,
|
||||
uint256 baseGas,
|
||||
uint256 gasPrice,
|
||||
address gasToken,
|
||||
address payable refundReceiver,
|
||||
bytes calldata signatures
|
||||
) external returns (bool success);
|
||||
|
||||
function requiredTxGas(address to, uint256 value, bytes calldata data, Operation operation)
|
||||
external
|
||||
returns (uint256);
|
||||
|
||||
function approveHash(bytes32 hashToApprove) external;
|
||||
|
||||
function signMessage(bytes calldata _data) external;
|
||||
|
||||
function isValidSignature(bytes calldata _data, bytes calldata _signature) external returns (bytes4);
|
||||
|
||||
function getMessageHash(bytes memory message) external view returns (bytes32);
|
||||
|
||||
function encodeTransactionData(
|
||||
address to,
|
||||
uint256 value,
|
||||
bytes memory data,
|
||||
Operation operation,
|
||||
uint256 safeTxGas,
|
||||
uint256 baseGas,
|
||||
uint256 gasPrice,
|
||||
address gasToken,
|
||||
address refundReceiver,
|
||||
uint256 _nonce
|
||||
) external view returns (bytes memory);
|
||||
|
||||
function getTransactionHash(
|
||||
address to,
|
||||
uint256 value,
|
||||
bytes memory data,
|
||||
Operation operation,
|
||||
uint256 safeTxGas,
|
||||
uint256 baseGas,
|
||||
uint256 gasPrice,
|
||||
address gasToken,
|
||||
address refundReceiver,
|
||||
uint256 _nonce
|
||||
) external view returns (bytes32);
|
||||
}
|
56
src/common/interfaces/IGovernance.sol
Normal file
56
src/common/interfaces/IGovernance.sol
Normal file
@ -0,0 +1,56 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.6.12;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
enum ProposalState {
|
||||
Pending,
|
||||
Active,
|
||||
Defeated,
|
||||
Timelocked,
|
||||
AwaitingExecution,
|
||||
Executed,
|
||||
Expired
|
||||
}
|
||||
|
||||
struct Proposal {
|
||||
// Creator of the proposal
|
||||
address proposer;
|
||||
// target addresses for the call to be made
|
||||
address target;
|
||||
// The block at which voting begins
|
||||
uint256 startTime;
|
||||
// The block at which voting ends: votes must be cast prior to this block
|
||||
uint256 endTime;
|
||||
// Current number of votes in favor of this proposal
|
||||
uint256 forVotes;
|
||||
// Current number of votes in opposition to this proposal
|
||||
uint256 againstVotes;
|
||||
// Flag marking whether the proposal has been executed
|
||||
bool executed;
|
||||
// Flag marking whether the proposal voting time has been extended
|
||||
// Voting time can be extended once, if the proposal outcome has changed during CLOSING_PERIOD
|
||||
bool extended;
|
||||
}
|
||||
|
||||
interface IGovernance {
|
||||
function initialized() external view returns (bool);
|
||||
function initializing() external view returns (bool);
|
||||
function EXECUTION_DELAY() external view returns (uint256);
|
||||
function EXECUTION_EXPIRATION() external view returns (uint256);
|
||||
function QUORUM_VOTES() external view returns (uint256);
|
||||
function PROPOSAL_THRESHOLD() external view returns (uint256);
|
||||
function VOTING_DELAY() external view returns (uint256);
|
||||
function VOTING_PERIOD() external view returns (uint256);
|
||||
function CLOSING_PERIOD() external view returns (uint256);
|
||||
function VOTE_EXTEND_TIME() external view returns (uint256);
|
||||
function torn() external view returns (address);
|
||||
function proposals(uint256 index) external view returns (Proposal memory);
|
||||
function lockedBalance(address account) external view returns (uint256);
|
||||
function propose(address target, string memory description) external returns (uint256);
|
||||
function castVote(uint256 proposalId, bool support) external;
|
||||
function lock(address owner, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;
|
||||
function lockWithApproval(uint256 amount) external;
|
||||
function execute(uint256 proposalId) external payable;
|
||||
function state(uint256 proposalId) external view returns (ProposalState);
|
||||
}
|
@ -73,7 +73,7 @@ library CurveChainedOracles {
|
||||
bytes4 _selector = _selectors[o];
|
||||
|
||||
// Index of the coin in the curve pool for second UINT256 selector
|
||||
uint8 _coin = _coins[0];
|
||||
uint8 _coin = _coins[o];
|
||||
|
||||
// Check whether the config actually works
|
||||
if (_selector == PRICE_ORACLE_SELECTOR) {
|
||||
@ -106,7 +106,8 @@ library CurveChainedOracles {
|
||||
uint256 priceDivisor = 1e18;
|
||||
uint256 inverseNumerator = 1e36;
|
||||
|
||||
uint256 numOracles = _oracle.length;
|
||||
// We know that each oracle addition encodes to exactly 26 bytes
|
||||
uint256 numOracles = _oracle.length / 26;
|
||||
|
||||
for (uint256 o = 0; o < numOracles; o++) {
|
||||
bytes32 chunk;
|
||||
@ -175,7 +176,7 @@ contract CurveFeeOracle is IFeeOracle {
|
||||
/* @dev For each instance, a set of data which translates to a set of chained price oracle calls, we call
|
||||
this data "chainedPriceOracles" because it encodes all data necessary to execute the chain and calc the
|
||||
price */
|
||||
mapping(ITornadoInstance => bytes) internal chainedPriceOracles;
|
||||
mapping(ITornadoInstance => bytes) public chainedPriceOracles;
|
||||
|
||||
/* @dev When setting, store the names as a historical record, key is keccak256(bytes) */
|
||||
mapping(bytes32 => string) public chainedPriceOracleNames;
|
||||
|
145
test/OracleTests.sol
Normal file
145
test/OracleTests.sol
Normal file
@ -0,0 +1,145 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.6.12;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
// OZ Imports
|
||||
|
||||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
|
||||
// Tornado imports
|
||||
|
||||
import { ITornadoInstance } from "tornado-anonymity-mining/contracts/interfaces/ITornadoInstance.sol";
|
||||
|
||||
// STD Imports
|
||||
|
||||
import { Test } from "forge-std/Test.sol";
|
||||
|
||||
import { console2 } from "forge-std/console2.sol";
|
||||
|
||||
// Local imports
|
||||
|
||||
import { IGovernance, Proposal } from "common/interfaces/IGovernance.sol";
|
||||
|
||||
import { TornadoAddresses } from "common/TornadoAddresses.sol";
|
||||
|
||||
import { UniswapV3FeeOracle } from "src/v2/UniswapV3FeeOracle.sol";
|
||||
|
||||
import { CurveFeeOracle, ICurvePriceOracle, CurveChainedOracles } from "src/v2/CurveFeeOracle.sol";
|
||||
|
||||
import { InstanceData } from "src/v2/InstanceRegistry.sol";
|
||||
|
||||
contract OracleTests is Test {
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VARIABLES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
address public constant crvUSDUSDCStableswap2Pool = 0x4DEcE678ceceb27446b35C672dC7d61F30bAD69E;
|
||||
|
||||
address public constant tricryptoUSDCPool = 0x7F86Bf177Dd4F3494b841a37e810A34dD56c829B;
|
||||
|
||||
ITornadoInstance public constant cu10_000 = ITornadoInstance(0x49f173CDAB99a2C3800F1255393DF9B7a17B82Bb);
|
||||
|
||||
IERC20 public constant TORN = IERC20(0x77777FeDdddFfC19Ff86DB637967013e6C6A116C);
|
||||
|
||||
UniswapV3FeeOracle v3FeeOracle;
|
||||
|
||||
CurveFeeOracle feeOracle;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TESTING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
function setUp() public {
|
||||
vm.createSelectFork(vm.envString("MAINNET_RPC_URL"));
|
||||
|
||||
v3FeeOracle = new UniswapV3FeeOracle(address(this));
|
||||
v3FeeOracle.setGlobalTornPoolFee(10_000, true);
|
||||
v3FeeOracle.setGlobalTwapIntervalSeconds(5400);
|
||||
v3FeeOracle.setGlobalMinObservationCardinality(10);
|
||||
|
||||
feeOracle = new CurveFeeOracle(address(this));
|
||||
feeOracle.setTornOracleIsUniswapV3(false);
|
||||
feeOracle.setUniswapV3FeeOracle(v3FeeOracle);
|
||||
}
|
||||
|
||||
function test_curveFeeSingleTricrypto() public {
|
||||
_setCurveFeeSimpleTricryptoOracleForInstance(feeOracle, cu10_000); // CRVUSD 10_000
|
||||
|
||||
console2.log(
|
||||
"\nShould be 30 * (ETH/USD) ------------------------------------------------\n",
|
||||
uint256(
|
||||
feeOracle.getFee(
|
||||
TORN, cu10_000, InstanceData(IERC20(cu10_000.token()), 0, true, true), 30, 10_000
|
||||
)
|
||||
),
|
||||
"\n------------------------------------------------------------------------\n"
|
||||
);
|
||||
}
|
||||
|
||||
function test_curveFeeChainedTORN() public {
|
||||
feeOracle.setTornOracleIsUniswapV3(true);
|
||||
|
||||
_setCurveFeeChainedOracleForInstance(feeOracle, cu10_000); // CRVUSD 10_000
|
||||
|
||||
console2.log(
|
||||
"\nTORN Fee calculated ------------------------------------------------------\n",
|
||||
uint256(
|
||||
feeOracle.getFee(
|
||||
TORN, cu10_000, InstanceData(IERC20(cu10_000.token()), 0, true, true), 30, 10_000
|
||||
)
|
||||
),
|
||||
"\n------------------------------------------------------------------------\n"
|
||||
);
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ HELPERS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
function _setCurveFeeSimpleTricryptoOracleForInstance(
|
||||
CurveFeeOracle _feeOracle,
|
||||
ITornadoInstance _instance
|
||||
) internal {
|
||||
ICurvePriceOracle[] memory _oracles = new ICurvePriceOracle[](1);
|
||||
|
||||
_oracles[0] = ICurvePriceOracle(tricryptoUSDCPool);
|
||||
|
||||
bytes4[] memory _selectors = new bytes4[](1);
|
||||
|
||||
_selectors[0] = CurveChainedOracles.PRICE_ORACLE_UINT256_SELECTOR;
|
||||
|
||||
uint8[] memory _coins = new uint8[](1);
|
||||
|
||||
_coins[0] = 1; // ETHER
|
||||
|
||||
bool[] memory _invert = new bool[](1);
|
||||
|
||||
_invert[0] = true;
|
||||
|
||||
_feeOracle.modifyChainedOracleForInstance(
|
||||
_instance, _oracles, _selectors, _coins, _invert, "ETH/CRVUSD"
|
||||
);
|
||||
}
|
||||
|
||||
function _setCurveFeeChainedOracleForInstance(CurveFeeOracle _feeOracle, ITornadoInstance _instance)
|
||||
internal
|
||||
{
|
||||
ICurvePriceOracle[] memory _oracles = new ICurvePriceOracle[](2);
|
||||
|
||||
_oracles[0] = ICurvePriceOracle(crvUSDUSDCStableswap2Pool);
|
||||
_oracles[1] = ICurvePriceOracle(tricryptoUSDCPool);
|
||||
|
||||
bytes4[] memory _selectors = new bytes4[](2);
|
||||
|
||||
_selectors[0] = CurveChainedOracles.PRICE_ORACLE_SELECTOR;
|
||||
_selectors[1] = CurveChainedOracles.PRICE_ORACLE_UINT256_SELECTOR;
|
||||
|
||||
uint8[] memory _coins = new uint8[](2);
|
||||
|
||||
_coins[1] = 1;
|
||||
|
||||
bool[] memory _invert = new bool[](2);
|
||||
|
||||
_invert[0] = false;
|
||||
_invert[1] = true;
|
||||
|
||||
_feeOracle.modifyChainedOracleForInstance(
|
||||
_instance, _oracles, _selectors, _coins, _invert, "ETH/CRVUSD"
|
||||
);
|
||||
}
|
||||
}
|
75
test/ProposalTests.sol
Normal file
75
test/ProposalTests.sol
Normal file
@ -0,0 +1,75 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.6.12;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
// OZ Imports
|
||||
|
||||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
|
||||
// Local imports
|
||||
|
||||
import { InfrastructureUpgradeProposal } from "src/proposals/InfrastructureUpgradeProposal.sol";
|
||||
|
||||
import { UniswapV3FeeOracle } from "src/v2/UniswapV3FeeOracle.sol";
|
||||
|
||||
import { CurveFeeOracle, ICurvePriceOracle, CurveChainedOracles } from "src/v2/CurveFeeOracle.sol";
|
||||
|
||||
import { InstanceRegistry } from "src/v2/InstanceRegistry.sol";
|
||||
|
||||
import { FeeOracleManager } from "src/v2/FeeOracleManager.sol";
|
||||
|
||||
import { TornadoRouter } from "src/v2/TornadoRouter.sol";
|
||||
|
||||
// Test imports
|
||||
|
||||
import { TornadoProposalTest } from "./TornadoProposalTest.sol";
|
||||
|
||||
contract ProposalTests is TornadoProposalTest {
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VARIABLES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
IERC20 public constant TORN = IERC20(0x77777FeDdddFfC19Ff86DB637967013e6C6A116C);
|
||||
|
||||
InstanceRegistry implInstanceRegisty;
|
||||
|
||||
UniswapV3FeeOracle v3FeeOracle;
|
||||
|
||||
FeeOracleManager feeOracleManager;
|
||||
|
||||
TornadoRouter router;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TESTING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
function setUp() public override {
|
||||
super.setUp();
|
||||
|
||||
implInstanceRegisty = new InstanceRegistry(address(governance));
|
||||
|
||||
v3FeeOracle = new UniswapV3FeeOracle(address(governance));
|
||||
|
||||
feeOracleManager = new FeeOracleManager(address(TORN), address(governance));
|
||||
|
||||
router = new TornadoRouter(address(governance));
|
||||
}
|
||||
|
||||
function test_infrastructureUpgradeProposalBasic() public {
|
||||
// Create proposal
|
||||
address proposal = address(
|
||||
new InfrastructureUpgradeProposal(
|
||||
address(v3FeeOracle),
|
||||
address(feeOracleManager),
|
||||
address(implInstanceRegisty),
|
||||
address(router)
|
||||
)
|
||||
);
|
||||
|
||||
// Propose
|
||||
uint256 id = easyPropose(proposal);
|
||||
|
||||
// Wait
|
||||
waitUntilExecutable(id);
|
||||
|
||||
// Exec
|
||||
governance.execute(id);
|
||||
}
|
||||
}
|
139
test/TornadoProposalTest.sol
Normal file
139
test/TornadoProposalTest.sol
Normal file
@ -0,0 +1,139 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.6.12;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import { IGovernance, Proposal } from "common/interfaces/IGovernance.sol";
|
||||
|
||||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
|
||||
import { Test } from "forge-std/Test.sol";
|
||||
|
||||
import { TornadoAddresses } from "common/TornadoAddresses.sol";
|
||||
|
||||
contract TornadoProposalTest is Test, TornadoAddresses {
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PERMIT ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
bytes32 public constant PERMIT_TYPEHASH =
|
||||
keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
|
||||
|
||||
bytes32 public 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 public constant PERMIT_FUNC_SELECTOR = uint16(0x1901);
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TEST DUMMIES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
address public constant TEST_REAL_ADDRESS_WITH_BALANCE = 0x9Ff3C1Bea9ffB56a78824FE29f457F066257DD58;
|
||||
|
||||
address public constant TEST_RELAYER_ADDRESS = 0x30F96AEF199B399B722F8819c9b0723016CEAe6C; // moon-relayer.eth
|
||||
// (just for testing)
|
||||
|
||||
uint256 public constant TEST_PRIVATE_KEY_ONE =
|
||||
0x66ddbd7cbe4a566df405f6ded0b908c669f88cdb1656380c050e3a457bd21df0;
|
||||
uint256 public constant TEST_PRIVATE_KEY_TWO =
|
||||
0xa4c8c98120e77741a87a116074a2df4ddb20d1149069290fd4a3d7ee65c55064;
|
||||
|
||||
address public constant TEST_ADDRESS_ONE = 0x118251976c65AFAf291f5255450ddb5b6A4d8B88;
|
||||
address public constant TEST_ADDRESS_TWO = 0x63aE7d90Eb37ca39FC62dD9991DbEfeE70673a20;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ADDRESSES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
address public constant VERIFIER_ADDRESS = 0x77777FeDdddFfC19Ff86DB637967013e6C6A116C;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GOVERNANCE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
string public constant PROPOSAL_DESCRIPTION = "{title:'Some proposal',description:''}";
|
||||
|
||||
uint256 public EXECUTION_DELAY;
|
||||
uint256 public EXECUTION_EXPIRATION;
|
||||
uint256 public QUORUM_VOTES;
|
||||
uint256 public PROPOSAL_THRESHOLD;
|
||||
uint256 public VOTING_DELAY;
|
||||
uint256 public VOTING_PERIOD;
|
||||
uint256 public CLOSING_PERIOD;
|
||||
uint256 public VOTE_EXTEND_TIME;
|
||||
|
||||
IGovernance public immutable governance = IGovernance(getGovernanceProxyAddress());
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TEST UTILS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
function setUp() public virtual {
|
||||
vm.createSelectFork(vm.envString("MAINNET_RPC_URL"));
|
||||
_fetchConfiguration();
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ HELPERS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
function waitUntilExecutable(uint256 proposalId) internal {
|
||||
uint256 proposalExecutableTime = getProposalExecutableTime(proposalId);
|
||||
require(block.timestamp < proposalExecutableTime, "Too late to execute proposal");
|
||||
vm.warp(proposalExecutableTime);
|
||||
}
|
||||
|
||||
function easyPropose(address proposalAddress) public returns (uint256) {
|
||||
retrieveAndLockBalance(TEST_PRIVATE_KEY_ONE, TEST_ADDRESS_ONE, QUORUM_VOTES);
|
||||
retrieveAndLockBalance(TEST_PRIVATE_KEY_TWO, TEST_ADDRESS_TWO, 1 ether);
|
||||
|
||||
/* ----------PROPOSER------------ */
|
||||
vm.startPrank(TEST_ADDRESS_ONE);
|
||||
|
||||
uint256 proposalId = governance.propose(proposalAddress, PROPOSAL_DESCRIPTION);
|
||||
|
||||
// TIME-TRAVEL
|
||||
vm.warp(block.timestamp + 6 hours);
|
||||
|
||||
governance.castVote(proposalId, true);
|
||||
|
||||
vm.stopPrank();
|
||||
/* ------------------------------ */
|
||||
|
||||
/* -------------VOTER-------------*/
|
||||
vm.startPrank(TEST_ADDRESS_TWO);
|
||||
governance.castVote(proposalId, true);
|
||||
vm.stopPrank();
|
||||
/* ------------------------------ */
|
||||
|
||||
return proposalId;
|
||||
}
|
||||
|
||||
function retrieveAndLockBalance(uint256, address voter, uint256 amount) internal {
|
||||
/* ----------GOVERNANCE------- */
|
||||
vm.startPrank(getGovernanceProxyAddress());
|
||||
IERC20(getTornTokenAddress()).transfer(voter, amount);
|
||||
vm.stopPrank();
|
||||
/* ----------------------------*/
|
||||
|
||||
/* ----------VOTER------------ */
|
||||
vm.startPrank(voter);
|
||||
IERC20(getTornTokenAddress()).approve(address(governance), amount);
|
||||
governance.lockWithApproval(amount);
|
||||
vm.stopPrank();
|
||||
/* ----------------------------*/
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GETTERS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
function getProposalExecutableTime(uint256 proposalId) internal view returns (uint256) {
|
||||
Proposal memory proposal = IGovernance(getGovernanceProxyAddress()).proposals(proposalId);
|
||||
return proposal.endTime + EXECUTION_DELAY + 1 hours;
|
||||
}
|
||||
|
||||
function _fetchConfiguration() internal {
|
||||
EXECUTION_DELAY = governance.EXECUTION_DELAY();
|
||||
EXECUTION_EXPIRATION = governance.EXECUTION_EXPIRATION();
|
||||
QUORUM_VOTES = governance.QUORUM_VOTES();
|
||||
PROPOSAL_THRESHOLD = governance.PROPOSAL_THRESHOLD();
|
||||
VOTING_DELAY = governance.VOTING_DELAY();
|
||||
VOTING_PERIOD = governance.VOTING_PERIOD();
|
||||
CLOSING_PERIOD = governance.CLOSING_PERIOD();
|
||||
VOTE_EXTEND_TIME = governance.VOTE_EXTEND_TIME();
|
||||
}
|
||||
}
|
@ -360,7 +360,12 @@ prettier-plugin-solidity@^1.0.0-beta.19:
|
||||
semver "^7.3.8"
|
||||
solidity-comments-extractor "^0.0.7"
|
||||
|
||||
prettier@^2.5.1, prettier@^2.8.3:
|
||||
prettier@^2.5.1:
|
||||
version "2.8.8"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da"
|
||||
integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==
|
||||
|
||||
prettier@^2.8.3:
|
||||
version "2.8.4"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.4.tgz#34dd2595629bfbb79d344ac4a91ff948694463c3"
|
||||
integrity sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw==
|
||||
|
Loading…
Reference in New Issue
Block a user