diff --git a/.solhint.json b/.solhint.json index 6def9e4..0ac0736 100644 --- a/.solhint.json +++ b/.solhint.json @@ -8,7 +8,8 @@ } ], "quotes": ["error", "double"], - "indent": ["error", 2] + "indent": ["error", 2], + "compiler-version": ["error", "^0.6.0"] }, "plugins": ["prettier"] } diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e84ae69 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "solidity.compileUsingRemoteVersion": "v0.6.12+commit.27d51765" +} \ No newline at end of file diff --git a/contracts/v2-vault-and-gas/gas/GasCompensator.sol b/contracts/v2-vault-and-gas/GasCompensator.sol similarity index 100% rename from contracts/v2-vault-and-gas/gas/GasCompensator.sol rename to contracts/v2-vault-and-gas/GasCompensator.sol diff --git a/contracts/v2-vault-and-gas/gas/GovernanceGasUpgrade.sol b/contracts/v2-vault-and-gas/GovernanceGasUpgrade.sol similarity index 98% rename from contracts/v2-vault-and-gas/gas/GovernanceGasUpgrade.sol rename to contracts/v2-vault-and-gas/GovernanceGasUpgrade.sol index f64c23c..272ad8a 100644 --- a/contracts/v2-vault-and-gas/gas/GovernanceGasUpgrade.sol +++ b/contracts/v2-vault-and-gas/GovernanceGasUpgrade.sol @@ -3,7 +3,7 @@ pragma solidity ^0.6.12; pragma experimental ABIEncoderV2; -import { GovernanceVaultUpgrade } from "../vault/GovernanceVaultUpgrade.sol"; +import { GovernanceVaultUpgrade } from "./GovernanceVaultUpgrade.sol"; import { GasCompensator } from "./GasCompensator.sol"; import { Math } from "@openzeppelin/contracts/math/Math.sol"; diff --git a/contracts/v2-vault-and-gas/vault/GovernanceVaultUpgrade.sol b/contracts/v2-vault-and-gas/GovernanceVaultUpgrade.sol similarity index 93% rename from contracts/v2-vault-and-gas/vault/GovernanceVaultUpgrade.sol rename to contracts/v2-vault-and-gas/GovernanceVaultUpgrade.sol index 6a48299..e13b0fe 100644 --- a/contracts/v2-vault-and-gas/vault/GovernanceVaultUpgrade.sol +++ b/contracts/v2-vault-and-gas/GovernanceVaultUpgrade.sol @@ -3,9 +3,9 @@ pragma solidity ^0.6.12; pragma experimental ABIEncoderV2; -import { Governance } from "../../v1/Governance.sol"; +import { Governance } from "../v1/Governance.sol"; import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; -import { ITornadoVault } from "../interfaces/ITornadoVault.sol"; +import { ITornadoVault } from "./interfaces/ITornadoVault.sol"; /// @title Version 2 Governance contract of the tornado.cash governance contract GovernanceVaultUpgrade is Governance { diff --git a/contracts/v2-vault-and-gas/ImmutableGovernanceInformation.sol b/contracts/v2-vault-and-gas/ImmutableGovernanceInformation.sol deleted file mode 100644 index 54db67a..0000000 --- a/contracts/v2-vault-and-gas/ImmutableGovernanceInformation.sol +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.6.12; -pragma experimental ABIEncoderV2; - -interface IGovernanceMultisigAddress { - function returnMultisigAddress() external pure returns (address); -} - -/** - * @notice Contract which hold governance information. Useful for avoiding code duplication. - * */ -contract ImmutableGovernanceInformation { - address internal constant GovernanceAddress = 0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce; - address internal constant TornTokenAddress = 0x77777FeDdddFfC19Ff86DB637967013e6C6A116C; - - modifier onlyGovernance() { - require(msg.sender == GovernanceAddress, "only governance"); - _; - } - - /** - * @dev this modifier calls the pure governance returnMultisigAddress() function, - * if governance version is not -> vault-and-gas upgrade <= version - * then this will not work! - */ - modifier onlyMultisig() { - require(msg.sender == IGovernanceMultisigAddress(GovernanceAddress).returnMultisigAddress(), "only multisig"); - _; - } - - /** - * @notice Function to return a payable version of the governance address. - * @return payable version of the address - * */ - function returnPayableGovernance() internal pure returns (address payable) { - return payable(GovernanceAddress); - } -} diff --git a/contracts/v2-vault-and-gas/VaultAndGasProposal.sol b/contracts/v2-vault-and-gas/VaultAndGasProposal.sol deleted file mode 100644 index cc9f0de..0000000 --- a/contracts/v2-vault-and-gas/VaultAndGasProposal.sol +++ /dev/null @@ -1,89 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.6.12; -pragma experimental ABIEncoderV2; - -import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { LoopbackProxy } from "tornado-governance/contracts/LoopbackProxy.sol"; - -import { TornadoVault } from "./vault/TornadoVault.sol"; -import { TornadoAuctionHandler } from "./auction/TornadoAuctionHandler.sol"; -import { GovernanceGasUpgrade } from "./gas/GovernanceGasUpgrade.sol"; - -import { IGovernanceVesting } from "./interfaces/IGovernanceVesting.sol"; -import { ImmutableGovernanceInformation } from "./ImmutableGovernanceInformation.sol"; - -/** - * @notice This proposal should upgrade governance to the vault and gas version without breaking any logic. - * */ -contract VaultAndGasProposal is ImmutableGovernanceInformation { - using SafeMath for uint256; - - IGovernanceVesting public constant GovernanceVesting = IGovernanceVesting(0x179f48C78f57A3A78f0608cC9197B8972921d1D2); - address public immutable gasCompLogic; - /// @notice the new voting period we would like to include - uint256 public immutable votingPeriod; - - event TornadoAuctionHandlerCreated(address indexed handler); - - constructor(address _gasCompLogic, uint256 _votingPeriod) public { - gasCompLogic = _gasCompLogic; - votingPeriod = _votingPeriod; - } - - /// @notice the entry point for the governance upgrade logic execution - /// @dev this function bundles all of the initialization logic for all of the contracts of the project - function executeProposal() external { - address vault = address(new TornadoVault()); - - LoopbackProxy(returnPayableGovernance()).upgradeTo(address(new GovernanceGasUpgrade(gasCompLogic, vault))); - - GovernanceGasUpgrade newGovernance = GovernanceGasUpgrade(returnPayableGovernance()); - IERC20 tornToken = IERC20(TornTokenAddress); - - newGovernance.setVotingPeriod(votingPeriod); - - /** - The below variable holds the total amount of TORN outflows from all of the proposal executions, - which will be used to calculate the proper amount of TORN for transfer to Governance. - For an explanation as to how this variable has been calculated with these fix values, please look at: - https://github.com/h-ivor/tornado-lottery-period/blob/production/scripts/balance_estimation.md - */ - uint256 totalOutflowsOfProposalExecutions = 120000000000000000000000 + - 22916666666666666666666 + - 54999999999999969408000 - - 27e18; - - require( - tornToken.transfer( - address(newGovernance.userVault()), - (tornToken.balanceOf(address(this))).sub(GovernanceVesting.released().sub(totalOutflowsOfProposalExecutions)) - ), - "TORN: transfer failed" - ); - - uint96 amountOfTornToAuctionOff = 787 ether; - uint96 minBuyAmount = 11 ether; - uint256 minBidInTorn = 10 ether; - uint256 fundingThreshold = 9 ether; - - TornadoAuctionHandler auctionHandler = new TornadoAuctionHandler(); - - emit TornadoAuctionHandlerCreated(address(auctionHandler)); - - tornToken.transfer(address(auctionHandler), amountOfTornToAuctionOff); - - /** - As with above, please see: - https://github.com/h-ivor/tornado-lottery-period/blob/production/contracts/auction/TornadoAuctionHandler.sol - */ - auctionHandler.initializeAuction( - block.timestamp + 5 days, - amountOfTornToAuctionOff, - minBuyAmount, - minBidInTorn, - fundingThreshold - ); - } -} diff --git a/contracts/v2-vault-and-gas/auction/Auction.md b/contracts/v2-vault-and-gas/auction/Auction.md deleted file mode 100644 index 0970810..0000000 --- a/contracts/v2-vault-and-gas/auction/Auction.md +++ /dev/null @@ -1,59 +0,0 @@ -# Auctioning some Tornado for compensations ETH - -To boost voting activity, one of our ideas is to compensate gas used for voting on proposals. -Both for the castVote and castDelegatedVote functionality. - -To make this as smooth as possible, we will compensate users directly in **ETH** (non-wrapped) for voting. -The priority fee is not compensated for, as to make exploiting the compensations unnecessary and unprofitable. - -In order to receive ETH, TORN will be auctioned off by the governance contract with the help of a auction helper -(see contracts/auction/TornadoAuctionHandler.sol). - -This contract has two functionalities: - -- Initiate an auction. - -- Convert all WETH it holds into ETH and send to Governance (callable by anyone). - -This way, Governance does not need to handle WETH swap logic (would require extra logic) and ETH will be directly sent to the governance contract. - -The initializeAuction function takes a couple of parameters: - -``` -function initializeAuction( - uint256 _auctionEndDate, - uint96 _auctionedSellAmount, - uint96 _minBuyAmount, - uint256 _minBidPerOrder, - uint256 _minFundingThreshold - ) external onlyGovernance { -``` - -- \_auctionEndDate -> the auction end date expressed in UNIX format. -- \_auctionedSellAmount -> the amount of TORN to be sold in the auction. -- \_minBuyAmount -> this variable helps to define the minimum price via the following formula: \_auctionedSellAmount/\_minBuyAmount, in other words the minimum amount of TORN per ETH. -- \_minBidPerOrder -> minimum buy amount per a single order (of tokens being auctioned), is also used to prevent users from buying too low amounts and hurting themselves. -- \_minFundingThreshold -> minimum amount of buy tokens (ETH) for the ENTIRE auction. If this is not reached, the auction reverts and all tokens are sent back to their original owners. - -This function does not take all the parameters for initializing the auction, the entire function may be seen below, some were left out of convenience: - -``` -IEasyAuction(EasyAuctionAddress).initiateAuction( - IERC20(TornTokenAddress), - IERC20(WETHAddress), - 0, // orderCancellationEndDate - _auctionEndDate, - _auctionedSellAmount, - _minBuyAmount, - _minBidPerOrder, - _minFundingThreshold, - true, // isAtomicClosureAllowed - address(0x0000000000000000000000000000000000000000), // access - new bytes(0) // access - ); -``` - -- Addresses of the tokens being bought/sold (ETH/TORN). -- orderCancellationEndDate -> date until order can be cancelled. For us, this is 0, meaning orders can't be cancelled once set. -- isAtomicClosureAllowed -> when auction end date is reached, a participant may set a last order in exchange for closing the auction, meaning it incentivizes the user to end the auction (gas payments, time saving) by giving him a risk-free action at the end. For us, false, due to tests showing that dust collection might not work if this is used. -- Last two fields are for access management, we have no whitelist for the auction, thus redundant and set to 0 for us. diff --git a/contracts/v2-vault-and-gas/auction/TornadoAuctionHandler.sol b/contracts/v2-vault-and-gas/auction/TornadoAuctionHandler.sol deleted file mode 100644 index fa5718a..0000000 --- a/contracts/v2-vault-and-gas/auction/TornadoAuctionHandler.sol +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.6.12; - -import { IWETH } from "./interfaces/IWETH.sol"; -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { EtherSend } from "../libraries/EtherSend.sol"; -import { IEasyAuction } from "./interfaces/IEasyAuction.sol"; -import { ImmutableGovernanceInformation } from "../ImmutableGovernanceInformation.sol"; - -/// @notice Handler which should help governance start an auction and transfer results of an auction to governance. -/// @dev The reasoning behind this contract is to not bloat governance with unnecessary logic. -contract TornadoAuctionHandler is ImmutableGovernanceInformation { - using EtherSend for address; - - address public constant EasyAuctionAddress = 0x0b7fFc1f4AD541A4Ed16b40D8c37f0929158D101; - address public constant WETHAddress = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; - - /// @notice main auction initialization function, please see: https://github.com/h-ivor/tornado-lottery-period/blob/only-vault-and-gas/contracts/auction/Auction.md - /// @dev calls easy auction deployed on eth mainnet - function initializeAuction( - uint256 _auctionEndDate, - uint96 _auctionedSellAmount, - uint96 _minBuyAmount, - uint256 _minBidPerOrder, - uint256 _minFundingThreshold - ) external onlyGovernance { - require(IERC20(TornTokenAddress).balanceOf(address(this)) >= _auctionedSellAmount, "torn balance not enough"); - IERC20(TornTokenAddress).approve(EasyAuctionAddress, _auctionedSellAmount); - - IEasyAuction(EasyAuctionAddress).initiateAuction( - IERC20(TornTokenAddress), - IERC20(WETHAddress), - 0, - _auctionEndDate, - _auctionedSellAmount, - _minBuyAmount, - _minBidPerOrder, - _minFundingThreshold, - false, - address(0x0000000000000000000000000000000000000000), - new bytes(0) - ); - } - - /// @notice function to transfer all eth and TORN dust to governance - function convertAndTransferToGovernance() external { - IWETH(WETHAddress).withdraw(IWETH(WETHAddress).balanceOf(address(this))); - if (address(this).balance > 0) require(GovernanceAddress.sendEther(address(this).balance), "pay fail"); - if (IERC20(TornTokenAddress).balanceOf(address(this)) > 0) - IERC20(TornTokenAddress).transfer(GovernanceAddress, IERC20(TornTokenAddress).balanceOf(address(this))); - } - - /// @notice receive eth that should only allow mainnet WETH to send eth - receive() external payable { - require(msg.sender == WETHAddress, "only weth"); - } -} diff --git a/contracts/v2-vault-and-gas/auction/interfaces/IEasyAuction.sol b/contracts/v2-vault-and-gas/auction/interfaces/IEasyAuction.sol deleted file mode 100644 index 1ddc4f7..0000000 --- a/contracts/v2-vault-and-gas/auction/interfaces/IEasyAuction.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.6.12; - -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; - -interface IEasyAuction { - function initiateAuction( - IERC20 _auctioningToken, - IERC20 _biddingToken, - uint256 orderCancellationEndDate, - uint256 auctionEndDate, - uint96 _auctionedSellAmount, - uint96 _minBuyAmount, - uint256 minimumBiddingAmountPerOrder, - uint256 minFundingThreshold, - bool isAtomicClosureAllowed, - address accessManagerContract, - bytes memory accessManagerContractData - ) external returns (uint256); -} diff --git a/contracts/v2-vault-and-gas/auction/interfaces/IPayableGovernance.sol b/contracts/v2-vault-and-gas/auction/interfaces/IPayableGovernance.sol deleted file mode 100644 index 6dd98fa..0000000 --- a/contracts/v2-vault-and-gas/auction/interfaces/IPayableGovernance.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.6.12; - -interface IPayableGovernance { - function receiveEther() external payable returns (bool); -} diff --git a/contracts/v2-vault-and-gas/auction/interfaces/IWETH.sol b/contracts/v2-vault-and-gas/auction/interfaces/IWETH.sol deleted file mode 100644 index 754e377..0000000 --- a/contracts/v2-vault-and-gas/auction/interfaces/IWETH.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.6.12; - -interface IWETH { - function balanceOf(address account) external view returns (uint256); - - function deposit() external payable; - - function withdraw(uint256 wad) external; - - function totalSupply() external view returns (uint256); - - function approve(address guy, uint256 wad) external returns (bool); - - function transfer(address dst, uint256 wad) external returns (bool); - - function transferFrom( - address src, - address dst, - uint256 wad - ) external returns (bool); -} diff --git a/contracts/v2-vault-and-gas/gas/GasCompensationVault.sol b/contracts/v2-vault-and-gas/gas/GasCompensationVault.sol deleted file mode 100644 index aa999c1..0000000 --- a/contracts/v2-vault-and-gas/gas/GasCompensationVault.sol +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.7; - -import { EtherSend } from "../libraries/EtherSend.sol"; - -interface IPayableGovernance { - function receiveEther() external payable returns (bool); -} - -/** - * @notice this contract should store ether for gas compensations and also retrieve the basefee - * */ -contract GasCompensationVault { - using EtherSend for address; - - address private constant GovernanceAddress = 0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce; - - modifier onlyGovernance() { - require(msg.sender == GovernanceAddress, "only gov"); - _; - } - - /** - * @notice function to compensate gas by sending amount eth to a recipient - * @param recipient address to receive amount eth - * @param gasAmount the amount of gas to be compensated - * */ - function compensateGas(address recipient, uint256 gasAmount) external onlyGovernance { - uint256 vaultBalance = address(this).balance; - uint256 toCompensate = gasAmount * block.basefee; - if (vaultBalance == 0) return; - payable(recipient).send((toCompensate > vaultBalance) ? vaultBalance : toCompensate); - } - - /** - * @notice function to withdraw compensate eth back to governance - * @param amount the amount of eth to withdraw back to governance - * */ - function withdrawToGovernance(uint256 amount) external onlyGovernance { - uint256 vaultBalance = address(this).balance; - require(GovernanceAddress.sendEther((amount > vaultBalance) ? vaultBalance : amount), "pay fail"); - } - - /** - * @notice receive ether function, does nothing but receive ether - * */ - receive() external payable {} -} diff --git a/contracts/v2-vault-and-gas/interfaces/IGovernanceVesting.sol b/contracts/v2-vault-and-gas/interfaces/IGovernanceVesting.sol deleted file mode 100644 index 621461f..0000000 --- a/contracts/v2-vault-and-gas/interfaces/IGovernanceVesting.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.6.12; -pragma experimental ABIEncoderV2; - -interface IGovernanceVesting { - function released() external view returns (uint256); -} diff --git a/contracts/v2-vault-and-gas/libraries/EtherSend.sol b/contracts/v2-vault-and-gas/libraries/EtherSend.sol deleted file mode 100644 index d7c4c0e..0000000 --- a/contracts/v2-vault-and-gas/libraries/EtherSend.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.6.12 || ^0.8.7; - -/// @notice very short library which implements a method to transfer ether via
.call -library EtherSend { - /** - * @notice function to transfer ether via filling the value field of a call - * @dev DICLAIMER: you must handle the possibility of reentrancy when using this function!!! - * @param to address to be transferred to - * @param amount amount to be transferred - * @return success true if transfer successful - * */ - function sendEther(address to, uint256 amount) internal returns (bool success) { - (success, ) = payable(to).call{ value: amount }(""); - } -} diff --git a/contracts/v2-vault-and-gas/testing/GasCompensationVault.sol b/contracts/v2-vault-and-gas/testing/GasCompensationVault.sol deleted file mode 100644 index 862eaf7..0000000 --- a/contracts/v2-vault-and-gas/testing/GasCompensationVault.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.7; - -contract GasCompensationVault { - address private constant GovernanceAddress = 0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce; - - modifier onlyGovernance() { - require(msg.sender == GovernanceAddress, "only gov"); - _; - } - - function compensateGas(address recipient, uint256 amount) external onlyGovernance { - if (address(this).balance == 0) return; - require( - (amount > address(this).balance) ? payable(recipient).send(address(this).balance) : payable(recipient).send(amount), - "compensation failed" - ); - } - - receive() external payable {} - - function getBasefee() external view returns (uint256) { - return 5; - } -} diff --git a/contracts/v2-vault-and-gas/testing/MockProposal1.sol b/contracts/v2-vault-and-gas/testing/MockProposal1.sol deleted file mode 100644 index e847cd6..0000000 --- a/contracts/v2-vault-and-gas/testing/MockProposal1.sol +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.6.12; - -import "tornado-governance/contracts/Governance.sol"; - -contract MockProposal1 { - address public constant GovernanceAddress = 0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce; - - function executeProposal() external { - Governance gov = Governance(GovernanceAddress); - - gov.setVotingPeriod(27000); - require(gov.VOTING_PERIOD() == 27000, "Voting period change failed!"); - } -} diff --git a/contracts/v2-vault-and-gas/testing/OrderEncoderHelper.sol b/contracts/v2-vault-and-gas/testing/OrderEncoderHelper.sol deleted file mode 100644 index 7cd7491..0000000 --- a/contracts/v2-vault-and-gas/testing/OrderEncoderHelper.sol +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.6.12; -pragma experimental ABIEncoderV2; - -import { IterableOrderedOrderSet } from "@gnosis.pm/ido-contracts/contracts/libraries/IterableOrderedOrderSet.sol"; - -contract OrderEncoderHelper { - function encodeOrder( - uint64 userId, - uint96 buyAmount, - uint96 sellAmount - ) external pure returns (bytes32) { - return IterableOrderedOrderSet.encodeOrder(userId, buyAmount, sellAmount); - } -} diff --git a/contracts/v2-vault-and-gas/vault/TornadoVault.sol b/contracts/v2-vault-and-gas/vault/TornadoVault.sol deleted file mode 100644 index eadfda1..0000000 --- a/contracts/v2-vault-and-gas/vault/TornadoVault.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.6.12; - -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; - -/// @title Vault which holds user funds -contract TornadoVault { - using SafeERC20 for IERC20; - - address internal constant TornTokenAddress = 0x77777FeDdddFfC19Ff86DB637967013e6C6A116C; - address internal constant GovernanceAddress = 0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce; - - /// @notice withdraws TORN from the contract - /// @param amount amount to withdraw - function withdrawTorn(address recipient, uint256 amount) external { - require(msg.sender == GovernanceAddress, "only gov"); - IERC20(TornTokenAddress).safeTransfer(recipient, amount); - } -} diff --git a/hardhat.config.js b/hardhat.config.js index 302ef13..7a3906f 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -23,24 +23,6 @@ module.exports = { }, }, }, - { - version: '0.8.7', - settings: { - optimizer: { - enabled: true, - runs: 1000, - }, - }, - }, - { - version: '0.7.6', - settings: { - optimizer: { - enabled: true, - runs: 1000, - }, - }, - }, ], }, networks: {