diff --git a/test/AbstractForkTest.sol b/test/AbstractForkTest.sol deleted file mode 100644 index 1745659..0000000 --- a/test/AbstractForkTest.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.23; - -import {Test} from "forge-std/Test.sol"; - -import {DeployManager} from "script/deploy/DeployManager.sol"; - -abstract contract AbstractForkTest is Test { - DeployManager internal deployManager; - - constructor() { - deployManager = new DeployManager(); - - // Run deployments - deployManager.setUp(); - deployManager.run(); - } -} diff --git a/test/OethARM.t.sol b/test/OethARM.t.sol deleted file mode 100644 index 72e7d0c..0000000 --- a/test/OethARM.t.sol +++ /dev/null @@ -1,182 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.23; - -import {Test, console2} from "forge-std/Test.sol"; -import {AbstractForkTest} from "./AbstractForkTest.sol"; - -import {IERC20} from "contracts/Interfaces.sol"; -import {OEthARM} from "contracts/OethARM.sol"; -import {Proxy} from "contracts/Proxy.sol"; -import {Addresses} from "contracts/utils/Addresses.sol"; - -contract OethARMTest is AbstractForkTest { - IERC20 constant weth = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); - IERC20 constant oeth = IERC20(0x856c4Efb76C1D1AE02e20CEB03A2A6a08b0b8dC3); - IERC20 BAD_TOKEN = IERC20(makeAddr("bad token")); - - address constant operator = Addresses.STRATEGIST; - - Proxy proxy; - OEthARM oethARM; - - function setUp() public { - proxy = Proxy(deployManager.getDeployment("OETH_ARM")); - oethARM = OEthARM(deployManager.getDeployment("OETH_ARM")); - - _dealWETH(address(oethARM), 100 ether); - _dealOETH(address(oethARM), 100 ether); - - vm.label(address(weth), "WETH"); - vm.label(address(oeth), "OETH"); - - // Only fuzz from this address. Big speedup on fork. - targetSender(address(this)); - } - - function test_swapExactTokensForTokens() external { - _swapExactTokensForTokens(oeth, weth, 10 ether, 10 ether); - } - - function test_swapTokensForExactTokens() external { - _swapTokensForExactTokens(oeth, weth, 10 ether, 10 ether); - } - - function _swapExactTokensForTokens(IERC20 inToken, IERC20 outToken, uint256 amountIn, uint256 expectedOut) - internal - { - if (inToken == weth) { - _dealWETH(address(this), amountIn + 1000); - } else { - _dealOETH(address(this), amountIn + 1000); - } - // Approve the ARM to transfer the input token of the swap. - inToken.approve(address(oethARM), amountIn); - - uint256 startIn = inToken.balanceOf(address(this)); - uint256 startOut = outToken.balanceOf(address(this)); - oethARM.swapExactTokensForTokens(inToken, outToken, amountIn, 0, address(this)); - assertEq(inToken.balanceOf(address(this)), startIn - amountIn, "In actual"); - assertEq(outToken.balanceOf(address(this)), startOut + expectedOut, "Out actual"); - } - - function _swapTokensForExactTokens(IERC20 inToken, IERC20 outToken, uint256 amountIn, uint256 expectedOut) - internal - { - if (inToken == weth) { - _dealWETH(address(this), amountIn + 1000); - } else { - _dealOETH(address(this), amountIn + 1000); - } - // Approve the ARM to transfer the input token of the swap. - inToken.approve(address(oethARM), amountIn); - - uint256 startIn = inToken.balanceOf(address(this)); - - oethARM.swapTokensForExactTokens(inToken, outToken, expectedOut, 3 * expectedOut, address(this)); - assertEq(inToken.balanceOf(address(this)), startIn - amountIn, "In actual"); - assertEq(outToken.balanceOf(address(this)), expectedOut, "Out actual"); - } - - function test_unauthorizedAccess() external { - address RANDOM_ADDRESS = 0xfEEDBeef00000000000000000000000000000000; - vm.startPrank(RANDOM_ADDRESS); - - // Proxy's restricted methods. - vm.expectRevert("ARM: Only owner can call this function."); - proxy.setOwner(RANDOM_ADDRESS); - - vm.expectRevert("ARM: Only owner can call this function."); - proxy.initialize(address(this), address(this), ""); - - vm.expectRevert("ARM: Only owner can call this function."); - proxy.upgradeTo(address(this)); - - vm.expectRevert("ARM: Only owner can call this function."); - proxy.upgradeToAndCall(address(this), ""); - - // Implementation's restricted methods. - vm.expectRevert("ARM: Only owner can call this function."); - oethARM.setOwner(RANDOM_ADDRESS); - } - - function test_wrongInTokenExactIn() external { - vm.expectRevert("ARM: Invalid swap"); - oethARM.swapExactTokensForTokens(BAD_TOKEN, oeth, 10 ether, 0, address(this)); - vm.expectRevert("ARM: Invalid swap"); - oethARM.swapExactTokensForTokens(BAD_TOKEN, weth, 10 ether, 0, address(this)); - vm.expectRevert("ARM: Invalid swap"); - oethARM.swapExactTokensForTokens(weth, weth, 10 ether, 0, address(this)); - vm.expectRevert("ARM: Invalid swap"); - oethARM.swapExactTokensForTokens(oeth, oeth, 10 ether, 0, address(this)); - } - - function test_wrongOutTokenExactIn() external { - vm.expectRevert("ARM: Invalid swap"); - oethARM.swapTokensForExactTokens(weth, BAD_TOKEN, 10 ether, 10 ether, address(this)); - vm.expectRevert("ARM: Invalid swap"); - oethARM.swapTokensForExactTokens(oeth, BAD_TOKEN, 10 ether, 10 ether, address(this)); - vm.expectRevert("ARM: Invalid swap"); - oethARM.swapTokensForExactTokens(weth, weth, 10 ether, 10 ether, address(this)); - vm.expectRevert("ARM: Invalid swap"); - oethARM.swapTokensForExactTokens(oeth, oeth, 10 ether, 10 ether, address(this)); - } - - function test_wrongInTokenExactOut() external { - vm.expectRevert("ARM: Invalid swap"); - oethARM.swapTokensForExactTokens(BAD_TOKEN, oeth, 10 ether, 10 ether, address(this)); - vm.expectRevert("ARM: Invalid swap"); - oethARM.swapTokensForExactTokens(BAD_TOKEN, weth, 10 ether, 10 ether, address(this)); - vm.expectRevert("ARM: Invalid swap"); - oethARM.swapTokensForExactTokens(weth, weth, 10 ether, 10 ether, address(this)); - vm.expectRevert("ARM: Invalid swap"); - oethARM.swapTokensForExactTokens(oeth, oeth, 10 ether, 10 ether, address(this)); - } - - function test_wrongOutTokenExactOut() external { - vm.expectRevert("ARM: Invalid swap"); - oethARM.swapTokensForExactTokens(weth, BAD_TOKEN, 10 ether, 10 ether, address(this)); - vm.expectRevert("ARM: Invalid swap"); - oethARM.swapTokensForExactTokens(oeth, BAD_TOKEN, 10 ether, 10 ether, address(this)); - vm.expectRevert("ARM: Invalid swap"); - oethARM.swapTokensForExactTokens(weth, weth, 10 ether, 10 ether, address(this)); - vm.expectRevert("ARM: Invalid swap"); - oethARM.swapTokensForExactTokens(oeth, oeth, 10 ether, 10 ether, address(this)); - } - - function test_collectTokens() external { - vm.startPrank(Addresses.TIMELOCK); - - oethARM.transferToken(address(weth), address(this), weth.balanceOf(address(oethARM))); - assertGt(weth.balanceOf(address(this)), 50 ether); - assertEq(weth.balanceOf(address(oethARM)), 0); - - oethARM.transferToken(address(oeth), address(this), oeth.balanceOf(address(oethARM))); - assertGt(oeth.balanceOf(address(this)), 50 ether); - assertLt(oeth.balanceOf(address(oethARM)), 3); - - vm.stopPrank(); - } - - function _dealOETH(address to, uint256 amount) internal { - vm.prank(0x8E02247D3eE0E6153495c971FFd45Aa131f4D7cB); - oeth.transfer(to, amount); - } - - function _dealWETH(address to, uint256 amount) internal { - deal(address(weth), to, amount); - } - - /* Operator Tests */ - - function test_setOperator() external { - vm.prank(Addresses.TIMELOCK); - oethARM.setOperator(address(this)); - assertEq(oethARM.operator(), address(this)); - } - - function test_nonOwnerCannotSetOperator() external { - vm.expectRevert("ARM: Only owner can call this function."); - vm.prank(operator); - oethARM.setOperator(operator); - } -} diff --git a/test/OethLiquidityManager.t.sol b/test/OethLiquidityManager.t.sol deleted file mode 100644 index 1a1eb6d..0000000 --- a/test/OethLiquidityManager.t.sol +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.23; - -import {console2} from "forge-std/Test.sol"; -import {AbstractForkTest} from "./AbstractForkTest.sol"; - -import {IERC20, IOethARM, IOETHVault} from "contracts/Interfaces.sol"; -import {OEthARM} from "contracts/OethARM.sol"; -import {Proxy} from "contracts/Proxy.sol"; -import {Addresses} from "contracts/utils/Addresses.sol"; - -contract OethLiquidityManagerTest is AbstractForkTest { - address constant RANDOM_ADDRESS = 0xfEEDBeef00000000000000000000000000000000; - - address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; - address constant OETH = 0x856c4Efb76C1D1AE02e20CEB03A2A6a08b0b8dC3; - IERC20 constant oeth = IERC20(OETH); - IERC20 constant weth = IERC20(WETH); - - IOETHVault constant vault = IOETHVault(0x39254033945AA2E4809Cc2977E7087BEE48bd7Ab); - - Proxy proxy; - OEthARM oethARM; - - address constant operator = Addresses.STRATEGIST; - - function setUp() public { - vm.label(WETH, "WETH"); - vm.label(OETH, "OETH"); - - proxy = Proxy(deployManager.getDeployment("OETH_ARM")); - oethARM = OEthARM(deployManager.getDeployment("OETH_ARM")); - } - - function test_withdrawal() external { - uint256 amount = 1 ether; - _dealOEth(address(proxy), 10 ether); - // put some WETH in the vault - _dealWEth(address(vault), 10 ether); - - vm.startPrank(operator); - (uint256 requestId, uint256 queued) = oethARM.requestWithdrawal(1 ether); - - // Snapshot WETH balance - uint256 startBalance = weth.balanceOf(address(oethARM)); - - vault.addWithdrawalQueueLiquidity(); - - skip(10 minutes); - - // Claim the ETH. - oethARM.claimWithdrawal(requestId); - - // Ensure the balance increased. - assertGt(weth.balanceOf(address(oethARM)), startBalance, "Withdrawal did not increase WETH balance"); - - vm.stopPrank(); - } - - /* - * Admin tests. - * - */ - function test_unauthorizedAccess() external { - vm.startPrank(RANDOM_ADDRESS); - - vm.expectRevert("ARM: Only operator or owner can call this function."); - oethARM.requestWithdrawal(1 ether); - - vm.expectRevert("ARM: Only operator or owner can call this function."); - oethARM.claimWithdrawal(1); - - uint256[] memory requestIds = new uint256[](2); - requestIds[0] = 10; - requestIds[1] = 22; - - vm.expectRevert("ARM: Only operator or owner can call this function."); - oethARM.claimWithdrawals(requestIds); - } - - function _dealOEth(address to, uint256 amount) internal { - vm.prank(0x8E02247D3eE0E6153495c971FFd45Aa131f4D7cB); // OETH whale - oeth.transfer(to, amount); - } - - function _dealWEth(address to, uint256 amount) internal { - vm.prank(0xF04a5cC80B1E94C69B48f5ee68a08CD2F09A7c3E); // WETH whale - weth.transfer(to, amount); - } -} diff --git a/test/Proxy.t.sol b/test/Proxy.t.sol deleted file mode 100644 index 9f8cff7..0000000 --- a/test/Proxy.t.sol +++ /dev/null @@ -1,102 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.23; - -import {Vm} from "forge-std/Vm.sol"; -import {console2} from "forge-std/Test.sol"; -import {AbstractForkTest} from "./AbstractForkTest.sol"; - -import {OEthARM} from "contracts/OethARM.sol"; -import {Proxy} from "contracts/Proxy.sol"; -import {Addresses} from "contracts/utils/Addresses.sol"; - -contract ProxyTest is AbstractForkTest { - address constant RANDOM_ADDRESS = 0xfEEDBeef00000000000000000000000000000000; - - Proxy proxy; - OEthARM oethARM; - - address constant weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; - address constant oeth = 0x856c4Efb76C1D1AE02e20CEB03A2A6a08b0b8dC3; - - address constant owner = Addresses.TIMELOCK; - address constant operator = Addresses.STRATEGIST; - - function setUp() public { - vm.label(weth, "WETH"); - vm.label(oeth, "OETH"); - - proxy = Proxy(deployManager.getDeployment("OETH_ARM")); - oethARM = OEthARM(deployManager.getDeployment("OETH_ARM")); - } - - function test_upgrade() external { - OEthARM newImplementation1 = new OEthARM(); - vm.prank(owner); - proxy.upgradeTo(address(newImplementation1)); - assertEq(proxy.implementation(), address(newImplementation1)); - - // Ensure ownership was preserved. - assertEq(proxy.owner(), owner); - assertEq(oethARM.owner(), owner); - - // Ensure the storage was preserved through the upgrade. - assertEq(address(oethARM.token0()), oeth); - assertEq(address(oethARM.token1()), weth); - } - - function test_upgradeAndCall() external { - OEthARM newImplementation2 = new OEthARM(); - bytes memory data = abi.encodeWithSignature("setOperator(address)", address(0x123)); - - vm.prank(owner); - proxy.upgradeToAndCall(address(newImplementation2), data); - assertEq(proxy.implementation(), address(newImplementation2)); - - // Ensure ownership was preserved. - assertEq(proxy.owner(), owner); - assertEq(oethARM.owner(), owner); - - // Ensure the post upgrade code was run - assertEq(oethARM.operator(), address(0x123)); - } - - function test_setOwner() external { - assertEq(proxy.owner(), owner); - assertEq(oethARM.owner(), owner); - - // Update the owner. - address newOwner = RANDOM_ADDRESS; - vm.prank(owner); - proxy.setOwner(newOwner); - assertEq(proxy.owner(), newOwner); - assertEq(oethARM.owner(), newOwner); - - // Old owner (this) should now be unauthorized. - vm.expectRevert("ARM: Only owner can call this function."); - oethARM.setOwner(address(this)); - } - - function test_unauthorizedAccess() external { - // Proxy's restricted methods. - vm.prank(RANDOM_ADDRESS); - vm.expectRevert("ARM: Only owner can call this function."); - proxy.setOwner(RANDOM_ADDRESS); - - vm.prank(RANDOM_ADDRESS); - vm.expectRevert("ARM: Only owner can call this function."); - proxy.initialize(address(this), address(this), ""); - - vm.prank(RANDOM_ADDRESS); - vm.expectRevert("ARM: Only owner can call this function."); - proxy.upgradeTo(address(this)); - - vm.prank(RANDOM_ADDRESS); - vm.expectRevert("ARM: Only owner can call this function."); - proxy.upgradeToAndCall(address(this), ""); - - // Implementation's restricted methods. - vm.prank(RANDOM_ADDRESS); - vm.expectRevert("ARM: Only owner can call this function."); - oethARM.setOwner(RANDOM_ADDRESS); - } -} diff --git a/test/UniswapV2.t.sol b/test/UniswapV2.t.sol deleted file mode 100644 index 153a906..0000000 --- a/test/UniswapV2.t.sol +++ /dev/null @@ -1,81 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.23; - -import {Test, console2} from "forge-std/Test.sol"; -import {AbstractForkTest} from "./AbstractForkTest.sol"; - -import {IERC20} from "contracts/Interfaces.sol"; -import {OEthARM} from "contracts/OethARM.sol"; -import {Proxy} from "contracts/Proxy.sol"; -import {Addresses} from "contracts/utils/Addresses.sol"; - -// Tests for the Uniswap V2 Router compatible interface of OSwap. -contract UniswapV2Test is AbstractForkTest { - IERC20 weth = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); - IERC20 oeth = IERC20(0x856c4Efb76C1D1AE02e20CEB03A2A6a08b0b8dC3); - - address constant operator = Addresses.STRATEGIST; - - Proxy proxy; - OEthARM oethARM; - - function setUp() public { - proxy = Proxy(deployManager.getDeployment("OETH_ARM")); - oethARM = OEthARM(deployManager.getDeployment("OETH_ARM")); - - // Add liquidity to the test contract. - _dealWETH(address(this), 120 ether); - _dealOEth(address(this), 120 ether); - - // Add liquidity to the pool. - _dealWETH(address(oethARM), 120 ether); - _dealOEth(address(oethARM), 120 ether); - - weth.approve(address(oethARM), type(uint256).max); - oeth.approve(address(oethARM), type(uint256).max); - vm.label(address(weth), "WETH"); - vm.label(address(oeth), "stETH"); - } - - function _dealOEth(address to, uint256 amount) internal { - vm.prank(0x8E02247D3eE0E6153495c971FFd45Aa131f4D7cB); // OETH whale - oeth.transfer(to, amount); - } - - function _dealWETH(address to, uint256 amount) internal { - deal(address(weth), to, amount); - } - - function test_swapExactOEthForWeth() external { - address[] memory path = new address[](2); - path[0] = address(oeth); - path[1] = address(weth); - uint256 balanceBefore = weth.balanceOf(address(this)); - - uint256[] memory amounts = oethARM.swapExactTokensForTokens(100 ether, 99, path, address(this), block.timestamp); - - assertGt(amounts[0], 0, "amount[0] should not be zero"); - assertGt(amounts[1], 0, "amount[1] should not be zero"); - assertGe(weth.balanceOf(address(this)), balanceBefore + amounts[1], "received all output amount"); - } - - function test_swapStEthForExactWeth() external { - address[] memory path = new address[](2); - path[0] = address(oeth); - path[1] = address(weth); - uint256 balanceBefore = weth.balanceOf(address(this)); - - uint256[] memory amounts = - oethARM.swapTokensForExactTokens(100 ether, 101 ether, path, address(this), block.timestamp); - - assertGt(amounts[0], 0, "amount[0] should not be zero"); - assertGt(amounts[1], 0, "amount[1] should not be zero"); - assertGe(weth.balanceOf(address(this)), balanceBefore + amounts[1], "received all output amount"); - } - - function test_deadline() external { - address[] memory path = new address[](2); - vm.expectRevert("ARM: Deadline expired"); - oethARM.swapExactTokensForTokens(0, 0, path, address(this), block.timestamp - 1); - } -} diff --git a/test/fork/shared/Shared.sol b/test/fork/shared/Shared.sol deleted file mode 100644 index 31b3b90..0000000 --- a/test/fork/shared/Shared.sol +++ /dev/null @@ -1,104 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.23; - -// Test imports -import {Base_Test_} from "../../Base.sol"; - -// Contracts -import {Proxy} from "contracts/Proxy.sol"; -import {OEthARM} from "contracts/OethARM.sol"; - -// Interfaces -import {IERC20} from "contracts/Interfaces.sol"; -import {IOETHVault} from "contracts/Interfaces.sol"; - -// Utils -import {Mainnet} from "test/utils/Addresses.sol"; - -abstract contract Fork_Shared_Test_ is Base_Test_ { - uint256 public forkId; - - ////////////////////////////////////////////////////// - /// --- SETUP - ////////////////////////////////////////////////////// - function setUp() public virtual override { - super.setUp(); - - // 1. Create fork. - _createAndSelectFork(); - - // 2. Create users. - _generateAddresses(); - - // 3. Deploy contracts. - _deployContracts(); - - // 4. Label contracts. - _label(); - } - - ////////////////////////////////////////////////////// - /// --- HELPERS - ////////////////////////////////////////////////////// - function _createAndSelectFork() internal { - // Check if the PROVIDER_URL is set. - require(vm.envExists("PROVIDER_URL"), "PROVIDER_URL not set"); - - // Create and select a fork. - forkId = vm.createSelectFork(vm.envString("PROVIDER_URL")); - } - - function _generateAddresses() internal { - // Users. - alice = makeAddr("alice"); - deployer = makeAddr("deployer"); - operator = Mainnet.STRATEGIST; - - // Contracts. - oeth = IERC20(Mainnet.OETH); - weth = IERC20(Mainnet.WETH); - vault = IOETHVault(Mainnet.OETHVAULT); - } - - function _deployContracts() internal { - // Deploy Proxy. - proxy = new Proxy(); - - // Deploy OEthARM implementation. - address implementation = address(new OEthARM()); - vm.label(implementation, "OETH ARM IMPLEMENTATION"); - - // Initialize Proxy with OEthARM implementation. - proxy.initialize(implementation, Mainnet.TIMELOCK, ""); - - // Set the Proxy as the OEthARM. - oethARM = OEthARM(address(proxy)); - } - - function _label() internal { - vm.label(address(oeth), "OETH"); - vm.label(address(weth), "WETH"); - vm.label(address(vault), "OETH VAULT"); - vm.label(address(oethARM), "OETH ARM"); - vm.label(address(proxy), "OETH ARM PROXY"); - vm.label(Mainnet.STRATEGIST, "STRATEGIST"); - vm.label(Mainnet.WHALE_OETH, "WHALE OETH"); - vm.label(Mainnet.TIMELOCK, "TIMELOCK"); - vm.label(Mainnet.NULL, "NULL"); - } - - /// @notice Override `deal()` function to handle OETH special case. - function deal(address token, address to, uint256 amount) internal override { - // Handle OETH special case, as rebasing tokens are not supported by the VM. - if (token == address(oeth)) { - // Check than whale as enough OETH. - require(oeth.balanceOf(Mainnet.WHALE_OETH) >= amount, "Fork_Shared_Test_: Not enough OETH in WHALE_OETH"); - - // Transfer OETH from WHALE_OETH to the user. - vm.prank(Mainnet.WHALE_OETH); - oeth.transfer(to, amount); - } else { - super.deal(token, to, amount); - } - } -}