From 0042e7db3eacc220776e78ab934288b28d789fc4 Mon Sep 17 00:00:00 2001 From: eladmallel Date: Thu, 28 Sep 2023 17:24:27 -0500 Subject: [PATCH] burn: started testing ExcessETH --- .../test/foundry/governance/ExcessETH.t.sol | 103 ++++++++++++++++++ .../foundry/helpers/DeployUtilsExcessETH.sol | 43 ++++++++ .../test/foundry/helpers/ERC20Mock.sol | 16 +++ 3 files changed, 162 insertions(+) create mode 100644 packages/nouns-contracts/test/foundry/governance/ExcessETH.t.sol create mode 100644 packages/nouns-contracts/test/foundry/helpers/DeployUtilsExcessETH.sol diff --git a/packages/nouns-contracts/test/foundry/governance/ExcessETH.t.sol b/packages/nouns-contracts/test/foundry/governance/ExcessETH.t.sol new file mode 100644 index 0000000000..552d8ed966 --- /dev/null +++ b/packages/nouns-contracts/test/foundry/governance/ExcessETH.t.sol @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.19; + +import 'forge-std/Test.sol'; +import { DeployUtilsExcessETH } from '../helpers/DeployUtilsExcessETH.sol'; +import { NounsDAOExecutorV3 } from '../../../contracts/governance/NounsDAOExecutorV3.sol'; +import { INounsAuctionHouse } from '../../../contracts/interfaces/INounsAuctionHouse.sol'; +import { ExcessETH, INounsAuctionHouseV2, INounsDAOV3 } from '../../../contracts/governance/ExcessETH.sol'; + +contract DAOMock { + uint256 adjustedSupply; + + function setAdjustedTotalSupply(uint256 adjustedSupply_) external { + adjustedSupply = adjustedSupply_; + } + + function adjustedTotalSupply() external view returns (uint256) { + return adjustedSupply; + } +} + +contract AuctionMock is INounsAuctionHouseV2 { + uint256[] pricesHistory; + + function setPrices(uint256[] memory pricesHistory_) external { + // priceHistory.length = priceHistory_.length; + // for (uint256 i = 0; i < priceHistory_.length; i++) { + // priceHistory[i] = priceHistory_[i]; + // } + pricesHistory = pricesHistory_; + } + + function prices(uint256 auctionCount) + external + view + override + returns (INounsAuctionHouse.Settlement[] memory priceHistory_) + { + priceHistory_ = new INounsAuctionHouse.Settlement[](pricesHistory.length); + for (uint256 i; i < pricesHistory.length; ++i) { + priceHistory_[i].amount = pricesHistory[i]; + } + } + + function settleAuction() external {} + + function settleCurrentAndCreateNewAuction() external {} + + function createBid(uint256 nounId) external payable {} + + function pause() external {} + + function unpause() external {} + + function setTimeBuffer(uint256 timeBuffer) external {} + + function setReservePrice(uint256 reservePrice) external {} + + function setMinBidIncrementPercentage(uint8 minBidIncrementPercentage) external {} +} + +contract ExcessETHTest is DeployUtilsExcessETH { + DAOMock dao = new DAOMock(); + AuctionMock auction = new AuctionMock(); + NounsDAOExecutorV3 treasury; + ExcessETH excessETH; + + uint256 waitingPeriodEnd; + uint16 pastAuctionCount; + + function setUp() public { + waitingPeriodEnd = block.timestamp + 90 days; + pastAuctionCount = 90; + + treasury = _deployExecutorV3(address(dao)); + excessETH = _deployExcessETH(treasury, auction, waitingPeriodEnd, pastAuctionCount); + } + + function test_excessETH_beforeWaitingEnds_returnsZero() public { + vm.deal(address(treasury), 100 ether); + dao.setAdjustedTotalSupply(1); + setMeanPrice(1 ether); + + assertEq(excessETH.excessETH(), 0); + } + + function test_excessETH_afterWaitingEnds_justETHInTreasury_works() public { + vm.deal(address(treasury), 100 ether); + dao.setAdjustedTotalSupply(1); + setMeanPrice(1 ether); + vm.warp(waitingPeriodEnd + 1); + + assertEq(excessETH.excessETH(), 99 ether); + } + + function setMeanPrice(uint256 meanPrice) internal { + uint256[] memory prices = new uint256[](pastAuctionCount); + for (uint256 i = 0; i < pastAuctionCount; i++) { + prices[i] = meanPrice; + } + auction.setPrices(prices); + } +} diff --git a/packages/nouns-contracts/test/foundry/helpers/DeployUtilsExcessETH.sol b/packages/nouns-contracts/test/foundry/helpers/DeployUtilsExcessETH.sol new file mode 100644 index 0000000000..3363385354 --- /dev/null +++ b/packages/nouns-contracts/test/foundry/helpers/DeployUtilsExcessETH.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.19; + +import 'forge-std/Test.sol'; +import { DeployUtilsV3 } from './DeployUtilsV3.sol'; +import { NounsDAOExecutorV3 } from '../../../contracts/governance/NounsDAOExecutorV3.sol'; +import { ExcessETH, INounsAuctionHouseV2, INounsDAOV3 } from '../../../contracts/governance/ExcessETH.sol'; +import { WETH } from '../../../contracts/test/WETH.sol'; +import { ERC20Mock, RocketETHMock } from './ERC20Mock.sol'; +import { ERC1967Proxy } from '@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol'; +import { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; + +abstract contract DeployUtilsExcessETH is DeployUtilsV3 { + function _deployExecutorV3(address dao) internal returns (NounsDAOExecutorV3) { + NounsDAOExecutorV3 executor = NounsDAOExecutorV3( + payable(address(new ERC1967Proxy(address(new NounsDAOExecutorV3()), ''))) + ); + executor.initialize(dao, TIMELOCK_DELAY); + return executor; + } + + function _deployExcessETH( + NounsDAOExecutorV3 owner, + INounsAuctionHouseV2 auction, + uint256 waitingPeriodEnd, + uint16 pastAuctionCount + ) internal returns (ExcessETH excessETH) { + WETH weth = new WETH(); + ERC20Mock stETH = new ERC20Mock(); + RocketETHMock rETH = new RocketETHMock(); + + excessETH = new ExcessETH( + address(owner), + INounsDAOV3(owner.admin()), + auction, + IERC20(address(weth)), + stETH, + rETH, + waitingPeriodEnd, + pastAuctionCount + ); + } +} diff --git a/packages/nouns-contracts/test/foundry/helpers/ERC20Mock.sol b/packages/nouns-contracts/test/foundry/helpers/ERC20Mock.sol index 79cafa7214..e949c77034 100644 --- a/packages/nouns-contracts/test/foundry/helpers/ERC20Mock.sol +++ b/packages/nouns-contracts/test/foundry/helpers/ERC20Mock.sol @@ -44,3 +44,19 @@ contract ERC20Mock is ERC20 { wasTransferCalled = wasTransferCalled_; } } + +contract RocketETHMock is ERC20Mock { + uint256 rate; + + constructor() ERC20Mock() { + rate = 1; + } + + function setRate(uint256 rate_) public { + rate = rate_; + } + + function getEthValue(uint256 _rethAmount) external view returns (uint256) { + return _rethAmount * rate; + } +}